Revert "Revert "Add MIPS64r6 support for libpixelflinger""

This reverts commit 7fd121788a.

Change-Id: Ic1204a8407c235b07c643764d5f2800631fecd72
This commit is contained in:
Elliott Hughes 2015-11-05 18:55:20 +00:00 committed by Ljubomir Papuga
parent f8e70a3a60
commit 606d4aecfb
32 changed files with 5035 additions and 279 deletions

View file

@ -50,6 +50,14 @@ PIXELFLINGER_SRC_FILES_mips := \
arch-mips/t32cb16blend.S \
endif
PIXELFLINGER_SRC_FILES_mips64 := \
codeflinger/MIPSAssembler.cpp \
codeflinger/MIPS64Assembler.cpp \
codeflinger/mips64_disassem.c \
arch-mips64/col32cb16blend.S \
arch-mips64/t32cb16blend.S \
#
# Shared library
#
@ -59,6 +67,7 @@ LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64)
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) \

View file

@ -0,0 +1,134 @@
/*
** Copyright 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.
*/
.macro pixel dreg src f sR sG sB shift
#if __mips==32 && __mips_isa_rev>=2
/* extract red */
ext $t4,\src,\shift+11,5
mul $t4,$t4,\f
/* extract green */
ext $t5,\src,\shift+5,6
mul $t5,$t5,\f
/* extract blue */
ext $t6,\src,\shift,5
mul $t6,$t6,\f
#else
/* extract red */
srl $t4,\src,\shift+11
andi $t4, 0x1f
mul $t4,$t4,\f
/* extract green */
srl $t5,\src,\shift+5
andi $t5, 0x3f
mul $t5,$t5,\f
/* extract blue */
srl $t6,\src,\shift
andi $t6, 0x1f
mul $t6,$t6,\f
#endif
srl $t4,$t4,8
srl $t5,$t5,8
srl $t6,$t6,8
addu $t4,$t4,\sR
addu $t5,$t5,\sG
addu \dreg,$t6,\sB
sll $t4,$t4,11
sll $t5,$t5,5
or \dreg,\dreg,$t4
or \dreg,\dreg,$t5
andi \dreg, 0xffff
.endm
.text
.align
.global scanline_col32cb16blend_mips
.ent scanline_col32cb16blend_mips
scanline_col32cb16blend_mips:
/* check if count is zero */
srl $v0,$a1,24 /* sA */
beqz $a2,done
li $t4, 0x100
srl $v1,$v0,7
addu $v0,$v1,$v0
subu $v0,$t4,$v0 /* f */
#if __mips==32 && __mips_isa_rev>=2
ext $a3,$a1,3,5 /* sR */
ext $t0,$a1,10,6 /* sG */
ext $t1,$a1,19,5 /* sB */
#else
srl $a3, $a1, 3
andi $a3, 0x1f /* sR */
srl $t0, $a1, 10
andi $t0, 0x3f /* sG */
srl $t1, $a1, 19
andi $t1, 0x1f /* sB */
#endif
/* check if cnt is at least 4 */
addiu $a2,$a2,-4
bltz $a2,tail
loop_4pixels:
lw $t7,0($a0)
lw $t8,4($a0)
addiu $a0,$a0,8
addiu $a2,$a2,-4
pixel $t2 $t7 $v0 $a3 $t0 $t1 0
pixel $t3 $t7 $v0 $a3 $t0 $t1 16
#if __mips==32 && __mips_isa_rev>=2
ins $t2,$t3,16,16
#else
sll $t3, 16
or $t2, $t2, $t3
#endif
pixel $t7 $t8 $v0 $a3 $t0 $t1 0
pixel $t3 $t8 $v0 $a3 $t0 $t1 16
#if __mips==32 && __mips_isa_rev>=2
ins $t7,$t3,16,16
#else
sll $t3, 16
or $t7, $t7, $t3
#endif
sw $t2,-8($a0)
sw $t7,-4($a0)
bgez $a2, loop_4pixels
tail:
/* the pixel count underran, restore it now */
addiu $a2,$a2,4
/* handle the last 0..3 pixels */
beqz $a2,done
loop_1pixel:
lhu $t7,0($a0)
addiu $a0,$a0,2
addiu $a2,$a2,-1
pixel $t2 $t7 $v0 $a3 $t0 $t1 0
sh $t2, -2($a0)
bnez $a2,loop_1pixel
done:
j $ra
.end scanline_col32cb16blend_mips

View file

@ -33,232 +33,241 @@
*/
#if __mips==32 && __mips_isa_rev>=2
.macro pixel dreg src fb shift
/*
* sA = s >> 24
* f = 0x100 - (sA + (sA>>7))
*/
DBG .set noat
DBG rdhwr $at,$2
DBG .set at
.macro pixel dreg src fb shift
/*
* sA = s >> 24
* f = 0x100 - (sA + (sA>>7))
*/
DBG .set noat
DBG rdhwr $at,$2
DBG .set at
srl $t7,\src,24
srl $t6,$t7,7
addu $t7,$t6
li $t6,0x100
subu $t7,$t6,$t7
srl $t7,\src,24
srl $t6,$t7,7
addu $t7,$t6
li $t6,0x100
subu $t7,$t6,$t7
/* red */
ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
mul $t6,$t8,$t7
ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
ext $t8,\src,3,5 # src[7..3]
srl $t6,8
addu $t8,$t6
ins \fb,$t8,\shift+6+5,5 # dst[\shift:15..11]
/* red */
ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
mul $t6,$t8,$t7
ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
ext $t8,\src,3,5 # src[7..3]
srl $t6,8
addu $t8,$t6
.if \shift!=0
sll $t8,\shift+11
or \fb,$t8
.else
sll \fb,$t8,11
.endif
/* green */
mul $t8,$t0,$t7
ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
ext $t6,\src,2+8,6 # src[15..10]
srl $t8,8
addu $t8,$t6
/* green */
mul $t8,$t0,$t7
ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
ext $t6,\src,2+8,6 # src[15..10]
srl $t8,8
addu $t8,$t6
/* blue */
mul $t0,$t0,$t7
ins \fb,$t8,\shift+5,6 # finish green insertion dst[\shift:10..5]
ext $t6,\src,(3+8+8),5
srl $t8,$t0,8
addu $t8,$t6
ins \fb,$t8,\shift,5
/* blue */
mul $t0,$t0,$t7
sll $t8, $t8, \shift+5
or \fb, \fb, $t8
ext $t6,\src,(3+8+8),5
srl $t8,$t0,8
addu $t8,$t6
sll $t8, $t8, \shift
or \fb, \fb, $t8
DBG .set noat
DBG rdhwr $t8,$2
DBG subu $t8,$at
DBG sltu $at,$t8,$v0
DBG movn $v0,$t8,$at
DBG sgtu $at,$t8,$v1
DBG movn $v1,$t8,$at
DBG .set at
.endm
DBG .set noat
DBG rdhwr $t8,$2
DBG subu $t8,$at
DBG sltu $at,$t8,$v0
DBG movn $v0,$t8,$at
DBG sgtu $at,$t8,$v1
DBG movn $v1,$t8,$at
DBG .set at
.endm
#else
.macro pixel dreg src fb shift
/*
* sA = s >> 24
* f = 0x100 - (sA + (sA>>7))
*/
DBG .set push
DBG .set noat
DBG .set mips32r2
DBG rdhwr $at,$2
DBG .set pop
.macro pixel dreg src fb shift
/*
* sA = s >> 24
* f = 0x100 - (sA + (sA>>7))
*/
DBG .set push
DBG .set noat
DBG .set mips32r2
DBG rdhwr $at,$2
DBG .set pop
srl $t7,\src,24
srl $t6,$t7,7
addu $t7,$t6
li $t6,0x100
subu $t7,$t6,$t7
srl $t7,\src,24
srl $t6,$t7,7
addu $t7,$t6
li $t6,0x100
subu $t7,$t6,$t7
/*
* red
* dR = (d >> (6 + 5)) & 0x1f;
* dR = (f*dR)>>8
* sR = (s >> ( 3)) & 0x1f;
* sR += dR
* fb |= sR << 11
*/
srl $t8,\dreg,\shift+6+5
/*
* red
* dR = (d >> (6 + 5)) & 0x1f;
* dR = (f*dR)>>8
* sR = (s >> ( 3)) & 0x1f;
* sR += dR
* fb |= sR << 11
*/
srl $t8,\dreg,\shift+6+5
.if \shift==0
and $t8,0x1f
and $t8,0x1f
.endif
mul $t8,$t8,$t7
srl $t6,\src,3
and $t6,0x1f
srl $t8,8
addu $t8,$t6
mul $t8,$t8,$t7
srl $t6,\src,3
and $t6,0x1f
srl $t8,8
addu $t8,$t6
.if \shift!=0
sll $t8,\shift+11
or \fb,$t8
sll $t8,\shift+11
or \fb,$t8
.else
sll \fb,$t8,11
sll \fb,$t8,11
.endif
/*
* green
* dG = (d >> 5) & 0x3f
* dG = (f*dG) >> 8
* sG = (s >> ( 8+2))&0x3F;
*/
srl $t8,\dreg,\shift+5
and $t8,0x3f
mul $t8,$t8,$t7
srl $t6,\src,8+2
and $t6,0x3f
srl $t8,8
addu $t8,$t6
sll $t8,\shift + 5
or \fb,$t8
* green
* dG = (d >> 5) & 0x3f
* dG = (f*dG) >> 8
* sG = (s >> ( 8+2))&0x3F;
*/
srl $t8,\dreg,\shift+5
and $t8,0x3f
mul $t8,$t8,$t7
srl $t6,\src,8+2
and $t6,0x3f
srl $t8,8
addu $t8,$t6
sll $t8,\shift + 5
or \fb,$t8
/* blue */
/* blue */
.if \shift!=0
srl $t8,\dreg,\shift
and $t8,0x1f
srl $t8,\dreg,\shift
and $t8,0x1f
.else
and $t8,\dreg,0x1f
and $t8,\dreg,0x1f
.endif
mul $t8,$t8,$t7
srl $t6,\src,(8+8+3)
and $t6,0x1f
srl $t8,8
addu $t8,$t6
mul $t8,$t8,$t7
srl $t6,\src,(8+8+3)
and $t6,0x1f
srl $t8,8
addu $t8,$t6
.if \shift!=0
sll $t8,\shift
sll $t8,\shift
.endif
or \fb,$t8
DBG .set push
DBG .set noat
DBG .set mips32r2
DBG rdhwr $t8,$2
DBG subu $t8,$at
DBG sltu $at,$t8,$v0
DBG movn $v0,$t8,$at
DBG sgtu $at,$t8,$v1
DBG movn $v1,$t8,$at
DBG .set pop
.endm
or \fb,$t8
DBG .set push
DBG .set noat
DBG .set mips32r2
DBG rdhwr $t8,$2
DBG subu $t8,$at
DBG sltu $at,$t8,$v0
DBG movn $v0,$t8,$at
DBG sgtu $at,$t8,$v1
DBG movn $v1,$t8,$at
DBG .set pop
.endm
#endif
.text
.align
.text
.align
.global scanline_t32cb16blend_mips
.ent scanline_t32cb16blend_mips
.global scanline_t32cb16blend_mips
.ent scanline_t32cb16blend_mips
scanline_t32cb16blend_mips:
DBG li $v0,0xffffffff
DBG li $v1,0
/* Align the destination if necessary */
and $t0,$a0,3
beqz $t0,aligned
DBG li $v0,0xffffffff
DBG li $v1,0
/* Align the destination if necessary */
and $t0,$a0,3
beqz $t0,aligned
/* as long as there is at least one pixel */
beqz $a2,done
/* as long as there is at least one pixel */
beqz $a2,done
lw $t4,($a1)
addu $a0,2
addu $a1,4
beqz $t4,1f
lhu $t3,-2($a0)
pixel $t3,$t4,$t1,0
sh $t1,-2($a0)
1: subu $a2,1
lw $t4,($a1)
addu $a0,2
addu $a1,4
beqz $t4,1f
lhu $t3,-2($a0)
pixel $t3,$t4,$t1,0
sh $t1,-2($a0)
1: subu $a2,1
aligned:
/* Check to see if its worth unrolling the loop */
subu $a2,4
bltz $a2,tail
/* Check to see if its worth unrolling the loop */
subu $a2,4
bltz $a2,tail
/* Process 4 pixels at a time */
/* Process 4 pixels at a time */
fourpixels:
/* 1st pair of pixels */
lw $t4,0($a1)
lw $t5,4($a1)
addu $a0,8
addu $a1,16
/* 1st pair of pixels */
lw $t4,0($a1)
lw $t5,4($a1)
addu $a0,8
addu $a1,16
/* both are zero, skip this pair */
or $t3,$t4,$t5
beqz $t3,1f
/* both are zero, skip this pair */
or $t3,$t4,$t5
beqz $t3,1f
/* load the destination */
lw $t3,-8($a0)
/* load the destination */
lw $t3,-8($a0)
pixel $t3,$t4,$t1,0
pixel $t3,$t5,$t1,16
sw $t1,-8($a0)
pixel $t3,$t4,$t1,0
andi $t1, 0xFFFF
pixel $t3,$t5,$t1,16
sw $t1,-8($a0)
1:
/* 2nd pair of pixels */
lw $t4,-8($a1)
lw $t5,-4($a1)
/* 2nd pair of pixels */
lw $t4,-8($a1)
lw $t5,-4($a1)
/* both are zero, skip this pair */
or $t3,$t4,$t5
beqz $t3,1f
/* both are zero, skip this pair */
or $t3,$t4,$t5
beqz $t3,1f
/* load the destination */
lw $t3,-4($a0)
/* load the destination */
lw $t3,-4($a0)
pixel $t3,$t4,$t1,0
pixel $t3,$t5,$t1,16
sw $t1,-4($a0)
pixel $t3,$t4,$t1,0
andi $t1, 0xFFFF
pixel $t3,$t5,$t1,16
sw $t1,-4($a0)
1: subu $a2,4
bgtz $a2,fourpixels
1: subu $a2,4
bgtz $a2,fourpixels
tail:
/* the pixel count underran, restore it now */
addu $a2,4
/* the pixel count underran, restore it now */
addu $a2,4
/* handle the last 0..3 pixels */
beqz $a2,done
/* handle the last 0..3 pixels */
beqz $a2,done
onepixel:
lw $t4,($a1)
addu $a0,2
addu $a1,4
beqz $t4,1f
lhu $t3,-2($a0)
pixel $t3,$t4,$t1,0
sh $t1,-2($a0)
1: subu $a2,1
bnez $a2,onepixel
lw $t4,($a1)
addu $a0,2
addu $a1,4
beqz $t4,1f
lhu $t3,-2($a0)
pixel $t3,$t4,$t1,0
sh $t1,-2($a0)
1: subu $a2,1
bnez $a2,onepixel
done:
DBG .set push
DBG .set mips32r2
DBG rdhwr $a0,$3
DBG mul $v0,$a0
DBG mul $v1,$a0
DBG .set pop
j $ra
.end scanline_t32cb16blend_mips
DBG .set push
DBG .set mips32r2
DBG rdhwr $a0,$3
DBG mul $v0,$a0
DBG mul $v1,$a0
DBG .set pop
j $ra
.end scanline_t32cb16blend_mips

View file

@ -0,0 +1,108 @@
/*
** Copyright 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.
*/
.macro pixel dreg src f sR sG sB shift
/* extract red */
.if \shift < 32
dext $t0,\src,\shift+11,5
.else
dextu $t0,\src,\shift+11,5
.endif
mul $t0,$t0,\f
/* extract green */
.if \shift < 32
dext $t1,\src,\shift+5,6
.else
dextu $t1,\src,\shift+5,6
.endif
mul $t1,$t1,\f
/* extract blue */
.if \shift < 32
dext $t2,\src,\shift,5
.else
dextu $t2,\src,\shift,5
.endif
mul $t2,$t2,\f
srl $t0,$t0,8
srl $t1,$t1,8
srl $t2,$t2,8
addu $t0,$t0,\sR
addu $t1,$t1,\sG
addu \dreg,$t2,\sB
sll $t0,$t0,11
sll $t1,$t1,5
or \dreg,\dreg,$t0
or \dreg,\dreg,$t1
.endm
.text
.align
.global scanline_col32cb16blend_mips64
.ent scanline_col32cb16blend_mips64
scanline_col32cb16blend_mips64:
/* check if count is zero */
srl $v0,$a1,24 /* sA */
beqz $a2,done
li $t0, 0x100
srl $v1,$v0,7
addu $v0,$v1,$v0
subu $v0,$t0,$v0 /* f */
ext $a3,$a1,3,5 /* sR */
ext $a4,$a1,10,6 /* sG */
ext $a5,$a1,19,5 /* sB */
/* check if cnt is at least 4 */
addiu $a2,$a2,-4
bltz $a2,tail
loop_4pixels:
ld $t3,0($a0)
daddiu $a0,$a0,8
addiu $a2,$a2,-4
pixel $a6 $t3 $v0 $a3 $a4 $a5 0
pixel $a7 $t3 $v0 $a3 $a4 $a5 16
pixel $t8 $t3 $v0 $a3 $a4 $a5 32
pixel $t9 $t3 $v0 $a3 $a4 $a5 48
dins $a6,$a7,16,16
dinsu $a6,$t8,32,16
dinsu $a6,$t9,48,16
sd $a6,-8($a0)
bgez $a2, loop_4pixels
tail:
/* the pixel count underran, restore it now */
addiu $a2,$a2,4
/* handle the last 0..3 pixels */
beqz $a2,done
loop_1pixel:
lhu $t3,0($a0)
daddiu $a0,$a0,2
addiu $a2,$a2,-1
pixel $a6 $t3 $v0 $a3 $a4 $a5 0
sh $a6, -2($a0)
bnez $a2,loop_1pixel
done:
j $ra
.end scanline_col32cb16blend_mips64

View file

@ -0,0 +1,172 @@
/*
** Copyright 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.
*/
#ifdef DEBUG
#define DBG
#else
#define DBG #
#endif
/*
* blend one of 2 16bpp RGB pixels held in dreg selected by shift
* with the 32bpp ABGR pixel held in src and store the result in fb
*
* Assumes that the dreg data is little endian and that
* the the second pixel (shift==16) will be merged into
* the fb result
*
* Uses $a4,$t2,$t3,$t8
*/
.macro pixel dreg src fb shift
/*
* sA = s >> 24
* f = 0x100 - (sA + (sA>>7))
*/
srl $t3,\src,24
srl $t2,$t3,7
addu $t3,$t2
li $t2,0x100
subu $t3,$t2,$t3
/* red */
ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
mul $t2,$t8,$t3
ext $a4,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
ext $t8,\src,3,5 # src[7..3]
srl $t2,8
addu $t8,$t2
.if \shift!=0
sll $t8,\shift+11 # dst[\shift:15..11]
or \fb,$t8
.else
sll \fb,$t8,11
.endif
/* green */
mul $t8,$a4,$t3
ext $a4,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
ext $t2,\src,2+8,6 # src[15..10]
srl $t8,8
addu $t8,$t2
/* blue */
mul $a4,$a4,$t3
sll $t8, $t8, \shift+5 # finish green insertion dst[\shift:10..5]
or \fb, \fb, $t8
ext $t2,\src,(3+8+8),5
srl $t8,$a4,8
addu $t8,$t2
sll $t8, $t8, \shift
or \fb, \fb, $t8
.endm
.text
.align
.global scanline_t32cb16blend_mips64
.ent scanline_t32cb16blend_mips64
scanline_t32cb16blend_mips64:
daddiu $sp, $sp, -40
DBG li $v0,0xffffffff
DBG li $v1,0
/* Align the destination if necessary */
and $a4,$a0,3
beqz $a4,aligned
/* as long as there is at least one pixel */
beqz $a2,done
lw $t0,($a1)
daddu $a0,2
daddu $a1,4
beqz $t0,1f
lhu $a7,-2($a0)
pixel $a7,$t0,$a5,0
sh $a5,-2($a0)
1: subu $a2,1
aligned:
/* Check to see if its worth unrolling the loop */
subu $a2,4
bltz $a2,tail
/* Process 4 pixels at a time */
fourpixels:
/* 1st pair of pixels */
lw $t0,0($a1)
lw $t1,4($a1)
daddu $a0,8
daddu $a1,16
/* both are zero, skip this pair */
or $a7,$t0,$t1
beqz $a7,1f
/* load the destination */
lw $a7,-8($a0)
pixel $a7,$t0,$a5,0
andi $a5, 0xFFFF
pixel $a7,$t1,$a5,16
sw $a5,-8($a0)
1:
/* 2nd pair of pixels */
lw $t0,-8($a1)
lw $t1,-4($a1)
/* both are zero, skip this pair */
or $a7,$t0,$t1
beqz $a7,1f
/* load the destination */
lw $a7,-4($a0)
pixel $a7,$t0,$a5,0
andi $a5, 0xFFFF
pixel $a7,$t1,$a5,16
sw $a5,-4($a0)
1: subu $a2,4
bgtz $a2,fourpixels
tail:
/* the pixel count underran, restore it now */
addu $a2,4
/* handle the last 0..3 pixels */
beqz $a2,done
onepixel:
lw $t0,($a1)
daddu $a0,2
daddu $a1,4
beqz $t0,1f
lhu $a7,-2($a0)
pixel $a7,$t0,$a5,0
sh $a5,-2($a0)
1: subu $a2,1
bnez $a2,onepixel
done:
DBG .set push
DBG .set mips32r2
DBG rdhwr $a0,$3
DBG mul $v0,$a0
DBG mul $v1,$a0
DBG .set pop
daddiu $sp, $sp, 40
j $ra
.end scanline_t32cb16blend_mips64

View file

@ -63,7 +63,7 @@ public:
};
enum {
CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64
CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64, CODEGEN_ARCH_MIPS64
};
// -----------------------------------------------------------------------
@ -115,7 +115,8 @@ public:
// data processing...
enum {
opAND, opEOR, opSUB, opRSB, opADD, opADC, opSBC, opRSC,
opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN
opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN,
opADD64, opSUB64
};
virtual void

View file

@ -893,7 +893,8 @@ void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits)
return;
}
if (getCodegenArch() == CODEGEN_ARCH_MIPS) {
if ((getCodegenArch() == CODEGEN_ARCH_MIPS) ||
(getCodegenArch() == CODEGEN_ARCH_MIPS64)) {
// MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr
// the below ' while (mask)' code is buggy on mips
// since mips returns true on isValidImmediate()
@ -1057,7 +1058,8 @@ RegisterAllocator::RegisterFile& RegisterAllocator::registerFile()
RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
: mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0)
{
if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) ||
(mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) {
mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
}
reserve(ARMAssemblerInterface::SP);
@ -1067,7 +1069,8 @@ RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch)
: mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0)
{
if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) ||
(mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) {
mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,429 @@
/* libs/pixelflinger/codeflinger/MIPS64Assembler.h
**
** Copyright 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.
*/
#ifndef ANDROID_MIPS64ASSEMBLER_H
#define ANDROID_MIPS64ASSEMBLER_H
#include <stdint.h>
#include <sys/types.h>
#include "utils/KeyedVector.h"
#include "utils/Vector.h"
#include "tinyutils/smartpointer.h"
#include "ARMAssemblerInterface.h"
#include "MIPSAssembler.h"
#include "CodeCache.h"
namespace android {
class MIPS64Assembler; // forward reference
// this class mimics ARMAssembler interface
// intent is to translate each ARM instruction to 1 or more MIPS instr
// implementation calls MIPS64Assembler class to generate mips code
class ArmToMips64Assembler : public ARMAssemblerInterface
{
public:
ArmToMips64Assembler(const sp<Assembly>& assembly,
char *abuf = 0, int linesz = 0, int instr_count = 0);
ArmToMips64Assembler(void* assembly);
virtual ~ArmToMips64Assembler();
uint32_t* base() const;
uint32_t* pc() const;
void disassemble(const char* name);
virtual void reset();
virtual int generate(const char* name);
virtual int getCodegenArch();
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual void comment(const char* string);
// for testing purposes
void fix_branches();
void set_condition(int mode, int R1, int R2);
// -----------------------------------------------------------------------
// shifters and addressing modes
// -----------------------------------------------------------------------
// shifters...
virtual bool isValidImmediate(uint32_t immed);
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
virtual uint32_t imm(uint32_t immediate);
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
virtual uint32_t reg_rrx(int Rm);
virtual uint32_t reg_reg(int Rm, int type, int Rs);
// addressing modes...
// LDR(B)/STR(B)/PLD
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
virtual uint32_t immed12_post(int32_t immed12);
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
// LDRH/LDRSB/LDRSH/STRH
// (immediate and Rm can be negative, which indicates U=0)
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
virtual uint32_t immed8_post(int32_t immed8);
virtual uint32_t reg_pre(int Rm, int W=0);
virtual uint32_t reg_post(int Rm);
virtual void dataProcessing(int opcode, int cc, int s,
int Rd, int Rn,
uint32_t Op2);
virtual void MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn);
virtual void MUL(int cc, int s,
int Rd, int Rm, int Rs);
virtual void UMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void UMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMULL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void SMUAL(int cc, int s,
int RdLo, int RdHi, int Rm, int Rs);
virtual void B(int cc, uint32_t* pc);
virtual void BL(int cc, uint32_t* pc);
virtual void BX(int cc, int Rn);
virtual void label(const char* theLabel);
virtual void B(int cc, const char* label);
virtual void BL(int cc, const char* label);
virtual uint32_t* pcForLabel(const char* label);
virtual void LDR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STR (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSB(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDRSH(int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void STRH (int cc, int Rd,
int Rn, uint32_t offset = 0);
virtual void LDM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void STM(int cc, int dir,
int Rn, int W, uint32_t reg_list);
virtual void SWP(int cc, int Rn, int Rd, int Rm);
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
virtual void SWI(int cc, uint32_t comment);
virtual void PLD(int Rn, uint32_t offset);
virtual void CLZ(int cc, int Rd, int Rm);
virtual void QADD(int cc, int Rd, int Rm, int Rn);
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
virtual void SMUL(int cc, int xy,
int Rd, int Rm, int Rs);
virtual void SMULW(int cc, int y,
int Rd, int Rm, int Rs);
virtual void SMLA(int cc, int xy,
int Rd, int Rm, int Rs, int Rn);
virtual void SMLAL(int cc, int xy,
int RdHi, int RdLo, int Rs, int Rm);
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
// bit manipulation...
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
// Address loading/storing/manipulation
virtual void ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_STR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
virtual void ADDR_ADD(int cc, int s, int Rd, int Rn, uint32_t Op2);
virtual void ADDR_SUB(int cc, int s, int Rd, int Rn, uint32_t Op2);
// this is some crap to share is MIPS64Assembler class for debug
char * mArmDisassemblyBuffer;
int mArmLineLength;
int mArmInstrCount;
int mInum; // current arm instuction number (0..n)
uint32_t** mArmPC; // array: PC for 1st mips instr of
// each translated ARM instr
private:
ArmToMips64Assembler(const ArmToMips64Assembler& rhs);
ArmToMips64Assembler& operator = (const ArmToMips64Assembler& rhs);
void init_conditional_labels(void);
void protectConditionalOperands(int Rd);
// reg__tmp set to MIPS AT, reg 1
int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
sp<Assembly> mAssembly;
MIPS64Assembler* mMips;
enum misc_constants_t {
ARM_MAX_INSTUCTIONS = 512 // based on ASSEMBLY_SCRATCH_SIZE
};
enum {
SRC_REG = 0,
SRC_IMM,
SRC_ERROR = -1
};
enum addr_modes {
// start above the range of legal mips reg #'s (0-31)
AMODE_REG = 0x20,
AMODE_IMM, AMODE_REG_IMM, // for data processing
AMODE_IMM_12_PRE, AMODE_IMM_12_POST, // for load/store
AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
AMODE_IMM_8_POST, AMODE_REG_PRE,
AMODE_UNSUPPORTED
};
struct addr_mode_t { // address modes for current ARM instruction
int reg;
int stype;
uint32_t value;
bool writeback; // writeback the adr reg after modification
} amode;
enum cond_types {
CMP_COND = 1,
SBIT_COND
};
struct cond_mode_t { // conditional-execution info for current ARM instruction
cond_types type;
int r1;
int r2;
int labelnum;
char label[100][10];
} cond;
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// This is the basic MIPS64 assembler, which just creates the opcodes in memory.
// All the more complicated work is done in ArmToMips64Assember above.
// Inherits MIPSAssembler class, and overrides only MIPS64r6 specific stuff
class MIPS64Assembler : public MIPSAssembler
{
public:
MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent);
MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent);
virtual ~MIPS64Assembler();
virtual void reset();
virtual void disassemble(const char* name);
void fix_branches();
// ------------------------------------------------------------------------
// MIPS64AssemblerInterface...
// ------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Arithmetic...
#endif
void DADDU(int Rd, int Rs, int Rt);
void DADDIU(int Rt, int Rs, int16_t imm);
void DSUBU(int Rd, int Rs, int Rt);
void DSUBIU(int Rt, int Rs, int16_t imm);
virtual void MUL(int Rd, int Rs, int Rt);
void MUH(int Rd, int Rs, int Rt);
#if 0
#pragma mark -
#pragma mark Logical...
#endif
virtual void CLO(int Rd, int Rs);
virtual void CLZ(int Rd, int Rs);
#if 0
#pragma mark -
#pragma mark Load/store...
#endif
void LD(int Rt, int Rbase, int16_t offset);
void SD(int Rt, int Rbase, int16_t offset);
virtual void LUI(int Rt, int16_t offset);
#if 0
#pragma mark -
#pragma mark Branch...
#endif
void JR(int Rs);
protected:
// void string_detab(char *s);
// void string_pad(char *s, int padded_len);
ArmToMips64Assembler *mParent;
sp<Assembly> mAssembly;
uint32_t* mBase;
uint32_t* mPC;
uint32_t* mPrologPC;
int64_t mDuration;
#if defined(WITH_LIB_HARDWARE)
bool mQemuTracing;
#endif
struct branch_target_t {
inline branch_target_t() : label(0), pc(0) { }
inline branch_target_t(const char* l, uint32_t* p)
: label(l), pc(p) { }
const char* label;
uint32_t* pc;
};
Vector<branch_target_t> mBranchTargets;
KeyedVector< const char*, uint32_t* > mLabels;
KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
KeyedVector< uint32_t*, const char* > mComments;
// opcode field of all instructions
enum opcode_field {
spec_op, regimm_op, j_op, jal_op, // 0x00 - 0x03
beq_op, bne_op, pop06_op, pop07_op, // 0x04 - 0x07
pop10_op, addiu_op, slti_op, sltiu_op, // 0x08 - 0x0b
andi_op, ori_op, xori_op, aui_op, // 0x0c - 0x0f
cop0_op, cop1_op, cop2_op, rsrv_opc_0, // 0x10 - 0x13
rsrv_opc_1, rsrv_opc_2, pop26_op, pop27_op, // 0x14 - 0x17
pop30_op, daddiu_op, rsrv_opc_3, rsrv_opc_4, // 0x18 - 0x1b
rsrv_opc_5, daui_op, msa_op, spec3_op, // 0x1c - 0x1f
lb_op, lh_op, rsrv_opc_6, lw_op, // 0x20 - 0x23
lbu_op, lhu_op, rsrv_opc_7, lwu_op, // 0x24 - 0x27
sb_op, sh_op, rsrv_opc_8, sw_op, // 0x28 - 0x2b
rsrv_opc_9, rsrv_opc_10, rsrv_opc_11, rsrv_opc_12, // 0x2c - 0x2f
rsrv_opc_13, lwc1_op, bc_op, rsrv_opc_14, // 0x2c - 0x2f
rsrv_opc_15, ldc1_op, pop66_op, ld_op, // 0x30 - 0x33
rsrv_opc_16, swc1_op, balc_op, pcrel_op, // 0x34 - 0x37
rsrv_opc_17, sdc1_op, pop76_op, sd_op // 0x38 - 0x3b
};
// func field for special opcode
enum func_spec_op {
sll_fn, rsrv_spec_0, srl_fn, sra_fn,
sllv_fn, lsa_fn, srlv_fn, srav_fn,
rsrv_spec_1, jalr_fn, rsrv_spec_2, rsrv_spec_3,
syscall_fn, break_fn, sdbbp_fn, sync_fn,
clz_fn, clo_fn, dclz_fn, dclo_fn,
dsllv_fn, dlsa_fn, dsrlv_fn, dsrav_fn,
sop30_fn, sop31_fn, sop32_fn, sop33_fn,
sop34_fn, sop35_fn, sop36_fn, sop37_fn,
add_fn, addu_fn, sub_fn, subu_fn,
and_fn, or_fn, xor_fn, nor_fn,
rsrv_spec_4, rsrv_spec_5, slt_fn, sltu_fn,
dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
tge_fn, tgeu_fn, tlt_fn, tltu_fn,
teq_fn, seleqz_fn, tne_fn, selnez_fn,
dsll_fn, rsrv_spec_6, dsrl_fn, dsra_fn,
dsll32_fn, rsrv_spec_7, dsrl32_fn, dsra32_fn
};
// func field for spec3 opcode
enum func_spec3_op {
ext_fn, dextm_fn, dextu_fn, dext_fn,
ins_fn, dinsm_fn, dinsu_fn, dins_fn,
cachee_fn = 0x1b, sbe_fn, she_fn, sce_fn, swe_fn,
bshfl_fn, prefe_fn = 0x23, dbshfl_fn, cache_fn, sc_fn, scd_fn,
lbue_fn, lhue_fn, lbe_fn = 0x2c, lhe_fn, lle_fn, lwe_fn,
pref_fn = 0x35, ll_fn, lld_fn, rdhwr_fn = 0x3b
};
// sa field for spec3 opcodes, with BSHFL function
enum func_spec3_bshfl {
bitswap_fn,
wsbh_fn = 0x02,
dshd_fn = 0x05,
seb_fn = 0x10,
seh_fn = 0x18
};
// rt field of regimm opcodes.
enum regimm_fn {
bltz_fn, bgez_fn,
dahi_fn = 0x6,
nal_fn = 0x10, bal_fn, bltzall_fn, bgezall_fn,
sigrie_fn = 0x17,
dati_fn = 0x1e, synci_fn
};
enum muldiv_fn {
mul_fn = 0x02, muh_fn
};
enum mips_inst_shifts {
OP_SHF = 26,
JTARGET_SHF = 0,
RS_SHF = 21,
RT_SHF = 16,
RD_SHF = 11,
RE_SHF = 6,
SA_SHF = RE_SHF, // synonym
IMM_SHF = 0,
FUNC_SHF = 0,
// mask values
MSK_16 = 0xffff,
CACHEOP_SHF = 18,
CACHESEL_SHF = 16,
};
};
}; // namespace android
#endif //ANDROID_MIPS64ASSEMBLER_H

View file

@ -1358,7 +1358,7 @@ void MIPSAssembler::disassemble(const char* name)
::mips_disassem(mipsPC, di_buf, arm_disasm_fmt);
string_detab(di_buf);
string_pad(di_buf, 30);
ALOGW("%08x: %08x %s", uint32_t(mipsPC), uint32_t(*mipsPC), di_buf);
ALOGW("%08x: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf);
mipsPC++;
}
}
@ -1407,7 +1407,7 @@ int MIPSAssembler::generate(const char* name)
#if defined(WITH_LIB_HARDWARE)
if (__builtin_expect(mQemuTracing, 0)) {
int err = qemu_add_mapping(int(base()), name);
int err = qemu_add_mapping(uintptr_t(base()), name);
mQemuTracing = (err >= 0);
}
#endif

View file

@ -244,20 +244,20 @@ public:
MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent);
virtual ~MIPSAssembler();
uint32_t* base() const;
uint32_t* pc() const;
void reset();
virtual uint32_t* base() const;
virtual uint32_t* pc() const;
virtual void reset();
void disassemble(const char* name);
virtual void disassemble(const char* name);
void prolog();
void epilog(uint32_t touched);
int generate(const char* name);
void comment(const char* string);
void label(const char* string);
virtual void prolog();
virtual void epilog(uint32_t touched);
virtual int generate(const char* name);
virtual void comment(const char* string);
virtual void label(const char* string);
// valid only after generate() has been called
uint32_t* pcForLabel(const char* label);
virtual uint32_t* pcForLabel(const char* label);
// ------------------------------------------------------------------------
@ -399,9 +399,9 @@ public:
private:
void string_detab(char *s);
void string_pad(char *s, int padded_len);
protected:
virtual void string_detab(char *s);
virtual void string_pad(char *s, int padded_len);
ArmToMipsAssembler *mParent;
sp<Assembly> mAssembly;
@ -537,7 +537,11 @@ private:
enum mips_regnames {
R_zero = 0,
R_at, R_v0, R_v1, R_a0, R_a1, R_a2, R_a3,
#if __mips_isa_rev < 6
R_t0, R_t1, R_t2, R_t3, R_t4, R_t5, R_t6, R_t7,
#else
R_a4, R_a5, R_a6, R_a7, R_t0, R_t1, R_t2, R_t3,
#endif
R_s0, R_s1, R_s2, R_s3, R_s4, R_s5, R_s6, R_s7,
R_t8, R_t9, R_k0, R_k1, R_gp, R_sp, R_s8, R_ra,
R_lr = R_s8,

View file

@ -0,0 +1,582 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include "mips_opcode.h"
#include <cutils/log.h>
static char *sprintf_buffer;
static int sprintf_buf_len;
typedef uint64_t db_addr_t;
static void db_printf(const char* fmt, ...);
static const char * const op_name[64] = {
/* 0 */ "spec", "bcond", "j", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "pop10", "addiu", "slti", "sltiu", "andi", "ori", "xori", "aui",
/*16 */ "cop0", "cop1", "cop2", "?", "?", "?", "pop26", "pop27",
/*24 */ "pop30", "daddiu", "?", "?", "?", "daui", "msa", "op37",
/*32 */ "lb", "lh", "?", "lw", "lbu", "lhu", "?", "lwu",
/*40 */ "sb", "sh", "?", "sw", "?", "?", "?", "?",
/*48 */ "?", "lwc1", "bc", "?", "?", "ldc1", "pop66", "ld",
/*56 */ "?", "swc1", "balc", "pcrel", "?", "sdc1", "pop76", "sd"
};
static const char * const spec_name[64] = {
/* 0 */ "sll", "?", "srl", "sra", "sllv", "?", "srlv", "srav",
/* 8 */ "?", "jalr", "?", "?", "syscall", "break", "sdbpp", "sync",
/*16 */ "clz", "clo", "dclz", "dclo", "dsllv", "dlsa", "dsrlv", "dsrav",
/*24 */ "sop30", "sop31", "sop32", "sop33", "sop34", "sop35", "sop36", "sop37",
/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
/*40 */ "?", "?", "slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
/*48 */ "tge", "tgeu", "tlt", "tltu", "teq", "seleqz", "tne", "selnez",
/*56 */ "dsll", "?", "dsrl", "dsra", "dsll32", "?", "dsrl32", "dsra32"
};
static const char * const bcond_name[32] = {
/* 0 */ "bltz", "bgez", "?", "?", "?", "?", "dahi", "?",
/* 8 */ "?", "?", "?", "?", "?", "?", "?", "?",
/*16 */ "nal", "bal", "?", "?", "?", "?", "?", "sigrie",
/*24 */ "?", "?", "?", "?", "?", "?", "dati", "synci",
};
static const char * const cop1_name[64] = {
/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
"fcmp.ole","fcmp.ule",
/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
"fcmp.le","fcmp.ngt"
};
static const char * const fmt_name[16] = {
"s", "d", "e", "fmt3",
"w", "fmt5", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
static char * const mips_reg_name[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM code
"zero", "at", "r0", "r1", "r2", "r3", "r4", "r5",
"r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13",
"r14", "r15", "at2", "cmp", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char ** reg_name = &mips_reg_name[0];
static const char * const c0_opname[64] = {
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
"eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
};
static const char * const c0_reg[32] = {
"index", "random", "tlblo0", "tlblo1",
"context", "pagemask", "wired", "cp0r7",
"badvaddr", "count", "tlbhi", "compare",
"status", "cause", "epc", "prid",
"config", "lladdr", "watchlo", "watchhi",
"xcontext", "cp0r21", "cp0r22", "debug",
"depc", "perfcnt", "ecc", "cacheerr",
"taglo", "taghi", "errepc", "desave"
};
static void print_addr(db_addr_t);
db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
/*
* Disassemble instruction 'insn' nominally at 'loc'.
* 'loc' may in fact contain a breakpoint instruction.
*/
static db_addr_t
db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
{
bool bdslot = false;
InstFmt i;
i.word = insn;
switch (i.JType.op) {
case OP_SPECIAL:
if (i.word == 0) {
db_printf("nop");
break;
}
if (i.word == 0x0080) {
db_printf("NIY");
break;
}
if (i.word == 0x00c0) {
db_printf("NOT IMPL");
break;
}
/* Special cases --------------------------------------------------
* "addu" is a "move" only in 32-bit mode. What's the correct
* answer - never decode addu/daddu as "move"?
*/
if ( (i.RType.func == OP_ADDU && i.RType.rt == 0) ||
(i.RType.func == OP_OR && i.RType.rt == 0) ) {
db_printf("move\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
}
if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
reg_name[i.RType.rt], i.RType.shamt);
break;
}
if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rt], reg_name[i.RType.rs]);
break;
}
if (i.RType.func == OP_SOP30) {
if (i.RType.shamt == OP_MUL) {
db_printf("mul");
} else if (i.RType.shamt == OP_MUH) {
db_printf("muh");
}
db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rs], reg_name[i.RType.rt]);
break;
}
if (i.RType.func == OP_SOP31) {
if (i.RType.shamt == OP_MUL) {
db_printf("mulu");
} else if (i.RType.shamt == OP_MUH) {
db_printf("muhu");
}
db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
reg_name[i.RType.rs], reg_name[i.RType.rt]);
break;
}
if (i.RType.func == OP_JALR && i.RType.rd == 0) {
db_printf("jr\t%s", reg_name[i.RType.rs]);
bdslot = true;
break;
}
db_printf("%s", spec_name[i.RType.func]);
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
case OP_SRA:
case OP_DSLL:
case OP_DSRL:
case OP_DSRA:
case OP_DSLL32:
case OP_DSRL32:
case OP_DSRA32:
db_printf("\t%s,%s,%d",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
i.RType.shamt);
break;
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
reg_name[i.RType.rs]);
break;
case OP_CLZ:
case OP_CLO:
case OP_DCLZ:
case OP_DCLO:
db_printf("\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
case OP_JALR:
db_printf("\t");
if (i.RType.rd != 31) {
db_printf("%s,", reg_name[i.RType.rd]);
}
db_printf("%s", reg_name[i.RType.rs]);
bdslot = true;
break;
case OP_SYSCALL:
case OP_SYNC:
break;
case OP_BREAK:
db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
break;
default:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
}
break;
case OP_SPECIAL3:
if (i.RType.func == OP_EXT)
db_printf("ext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_DEXT)
db_printf("dext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_DEXTM)
db_printf("dextm\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd+33);
else if (i.RType.func == OP_DEXTU)
db_printf("dextu\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt+32,
i.RType.rd+1);
else if (i.RType.func == OP_INS)
db_printf("ins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_DINS)
db_printf("dins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_DINSM)
db_printf("dinsm\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt,
i.RType.rd-i.RType.shamt+33);
else if (i.RType.func == OP_DINSU)
db_printf("dinsu\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.shamt+32,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
db_printf("wsbh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
db_printf("seb\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
db_printf("seh\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else if (i.RType.func == OP_RDHWR)
db_printf("rdhwr\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt]);
else
db_printf("Unknown");
break;
case OP_BCOND:
db_printf("%s\t%s,", bcond_name[i.IType.rt],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BLEZ:
case OP_BGTZ:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BEQ:
if (i.IType.rs == 0 && i.IType.rt == 0) {
db_printf("b\t");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
db_printf("%s\t%s,%s,", op_name[i.IType.op],
reg_name[i.IType.rs],
reg_name[i.IType.rt]);
pr_displ:
print_addr(loc + 4 + ((short)i.IType.imm << 2));
bdslot = true;
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc0%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMT:
db_printf("dmtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_MF:
db_printf("mfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMF:
db_printf("dmfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
default:
db_printf("%s", c0_opname[i.FRType.func]);
}
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc1%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MF:
db_printf("mfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CT:
db_printf("ctc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CF:
db_printf("cfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
default:
db_printf("%s.%s\tf%d,f%d,f%d",
cop1_name[i.FRType.func],
fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs, i.FRType.ft);
}
break;
case OP_J:
case OP_JAL:
db_printf("%s\t", op_name[i.JType.op]);
print_addr((loc & 0xFFFFFFFFF0000000) | (i.JType.target << 2));
bdslot = true;
break;
case OP_LWC1:
case OP_SWC1:
db_printf("%s\tf%d,", op_name[i.IType.op],
i.IType.rt);
goto loadstore;
case OP_LB:
case OP_LH:
case OP_LW:
case OP_LD:
case OP_LBU:
case OP_LHU:
case OP_LWU:
case OP_SB:
case OP_SH:
case OP_SW:
case OP_SD:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rt]);
loadstore:
db_printf("%d(%s)", (short)i.IType.imm,
reg_name[i.IType.rs]);
break;
case OP_ORI:
case OP_XORI:
if (i.IType.rs == 0) {
db_printf("li\t%s,0x%x",
reg_name[i.IType.rt],
i.IType.imm);
break;
}
/* FALLTHROUGH */
case OP_ANDI:
db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
i.IType.imm);
break;
case OP_AUI:
if (i.IType.rs == 0) {
db_printf("lui\t%s,0x%x", reg_name[i.IType.rt],
i.IType.imm);
} else {
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt], reg_name[i.IType.rs],
(short)i.IType.imm);
}
break;
case OP_ADDIU:
case OP_DADDIU:
if (i.IType.rs == 0) {
db_printf("li\t%s,%d",
reg_name[i.IType.rt],
(short)i.IType.imm);
break;
}
/* FALLTHROUGH */
default:
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
(short)i.IType.imm);
}
// db_printf("\n");
// if (bdslot) {
// db_printf(" bd: ");
// mips_disassem(loc+4);
// return (loc + 8);
// }
return (loc + 4);
}
static void
print_addr(db_addr_t loc)
{
db_printf("0x%08lx", loc);
}
static void db_printf(const char* fmt, ...)
{
int cnt;
va_list argp;
va_start(argp, fmt);
if (sprintf_buffer) {
cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
sprintf_buffer += cnt;
sprintf_buf_len -= cnt;
} else {
vprintf(fmt, argp);
}
}
/*
* Disassemble instruction at 'loc'.
* Return address of start of next instruction.
* Since this function is used by 'examine' and by 'step'
* "next instruction" does NOT mean the next instruction to
* be executed but the 'linear' next instruction.
*/
db_addr_t
mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
{
u_int32_t instr;
if (alt_dis_format) { // use ARM register names for disassembly
reg_name = &alt_arm_reg_name[0];
}
sprintf_buffer = di_buffer; // quick 'n' dirty printf() vs sprintf()
sprintf_buf_len = 39; // should be passed in
instr = *(u_int32_t *)loc;
return (db_disasm_insn(instr, loc, false));
}

View file

@ -0,0 +1,56 @@
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#ifndef ANDROID_MIPS_DISASSEM_H
#define ANDROID_MIPS_DISASSEM_H
#include <sys/types.h>
#if __cplusplus
extern "C" {
#endif
/* Prototypes for callable functions */
void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt);
#if __cplusplus
}
#endif
#endif /* !ANDROID_MIPS_DISASSEM_H */

View file

@ -323,14 +323,14 @@ db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
db_printf("ext\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.rd+1,
i.RType.shamt);
i.RType.shamt,
i.RType.rd+1);
else if (i.RType.func == OP_INS)
db_printf("ins\t%s,%s,%d,%d",
reg_name[i.RType.rt],
reg_name[i.RType.rs],
i.RType.rd+1,
i.RType.shamt);
i.RType.shamt,
i.RType.rd-i.RType.shamt+1);
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
db_printf("wsbh\t%s,%s",
reg_name[i.RType.rd],

View file

@ -125,69 +125,118 @@ typedef union {
#define OP_BLEZ 006
#define OP_BGTZ 007
#if __mips_isa_rev < 6
#define OP_ADDI 010
#else
#define OP_POP10 010
#endif
#define OP_ADDIU 011
#define OP_SLTI 012
#define OP_SLTIU 013
#define OP_ANDI 014
#define OP_ORI 015
#define OP_XORI 016
#if __mips_isa_rev < 6
#define OP_LUI 017
#else
#define OP_AUI 017
#endif
#define OP_COP0 020
#define OP_COP1 021
#define OP_COP2 022
#if __mips_isa_rev < 6
#define OP_COP3 023
#define OP_BEQL 024 /* MIPS-II, for r4000 port */
#define OP_BNEL 025 /* MIPS-II, for r4000 port */
#define OP_BLEZL 026 /* MIPS-II, for r4000 port */
#define OP_BGTZL 027 /* MIPS-II, for r4000 port */
#define OP_BEQL 024
#define OP_BNEL 025
#define OP_BLEZL 026
#define OP_BGTZL 027
#define OP_DADDI 030
#else
#define OP_POP26 026
#define OP_POP27 027
#define OP_POP30 030
#endif
#define OP_DADDI 030 /* MIPS-II, for r4000 port */
#define OP_DADDIU 031 /* MIPS-II, for r4000 port */
#define OP_LDL 032 /* MIPS-II, for r4000 port */
#define OP_LDR 033 /* MIPS-II, for r4000 port */
#define OP_DADDIU 031
#define OP_SPECIAL2 034 /* QED opcodes */
#define OP_SPECIAL3 037 /* mips32r2 opcodes */
#if __mips_isa_rev < 6
#define OP_LDL 032
#define OP_LDR 033
#define OP_SPECIAL2 034
#else
#define OP_DAUI 035
#endif
#define OP_SPECIAL3 037
#define OP_LB 040
#define OP_LH 041
#if __mips_isa_rev < 6
#define OP_LWL 042
#endif
#define OP_LW 043
#define OP_LBU 044
#define OP_LHU 045
#define OP_LWR 046
#define OP_LHU 045
#if __mips_isa_rev < 6
#define OP_LWR 046
#define OP_LWU 047 /* MIPS-II, for r4000 port */
#endif
#define OP_LWU 047
#define OP_SB 050
#define OP_SH 051
#define OP_SWL 052
#define OP_SW 053
#define OP_SDL 054 /* MIPS-II, for r4000 port */
#define OP_SDR 055 /* MIPS-II, for r4000 port */
#define OP_SWR 056
#define OP_CACHE 057 /* MIPS-II, for r4000 port */
#if __mips_isa_rev < 6
#define OP_SWL 052
#endif
#define OP_SW 053
#if __mips_isa_rev < 6
#define OP_SDL 054
#define OP_SDR 055
#define OP_SWR 056
#define OP_CACHE 057
#define OP_LL 060
#define OP_LWC0 OP_LL /* backwards source compatibility */
#define OP_LWC0 OP_LL
#define OP_LWC1 061
#define OP_LWC2 062
#define OP_LWC3 063
#define OP_LLD 064 /* MIPS-II, for r4000 port */
#define OP_LDC1 065
#define OP_LD 067 /* MIPS-II, for r4000 port */
#define OP_LLD 064
#else
#define OP_LWC1 061
#define OP_BC 062
#endif
#define OP_LDC1 065
#define OP_LD 067
#if __mips_isa_rev < 6
#define OP_SC 070
#define OP_SWC0 OP_SC /* backwards source compatibility */
#define OP_SWC0 OP_SC
#endif
#define OP_SWC1 071
#if __mips_isa_rev < 6
#define OP_SWC2 072
#define OP_SWC3 073
#define OP_SCD 074 /* MIPS-II, for r4000 port */
#define OP_SCD 074
#else
#define OP_BALC 072
#endif
#define OP_SDC1 075
#define OP_SD 077 /* MIPS-II, for r4000 port */
#define OP_SD 077
/*
* Values for the 'func' field when 'op' == OP_SPECIAL.
@ -199,28 +248,50 @@ typedef union {
#define OP_SRLV 006
#define OP_SRAV 007
#if __mips_isa_rev < 6
#define OP_JR 010
#endif
#define OP_JALR 011
#define OP_SYSCALL 014
#define OP_BREAK 015
#define OP_SYNC 017 /* MIPS-II, for r4000 port */
#define OP_SYNC 017
#if __mips_isa_rev < 6
#define OP_MFHI 020
#define OP_MTHI 021
#define OP_MFLO 022
#define OP_MTLO 023
#define OP_DSLLV 024 /* MIPS-II, for r4000 port */
#define OP_DSRLV 026 /* MIPS-II, for r4000 port */
#define OP_DSRAV 027 /* MIPS-II, for r4000 port */
#else
#define OP_CLZ 020
#define OP_CLO 021
#define OP_DCLZ 022
#define OP_DCLO 023
#endif
#define OP_DSLLV 024
#define OP_DSRLV 026
#define OP_DSRAV 027
#if __mips_isa_rev < 6
#define OP_MULT 030
#define OP_MULTU 031
#define OP_DIV 032
#define OP_DIVU 033
#define OP_DMULT 034 /* MIPS-II, for r4000 port */
#define OP_DMULTU 035 /* MIPS-II, for r4000 port */
#define OP_DDIV 036 /* MIPS-II, for r4000 port */
#define OP_DDIVU 037 /* MIPS-II, for r4000 port */
#define OP_DMULT 034
#define OP_DMULTU 035
#define OP_DDIV 036
#define OP_DDIVU 037
#else
#define OP_SOP30 030
#define OP_SOP31 031
#define OP_SOP32 032
#define OP_SOP33 033
#define OP_SOP34 034
#define OP_SOP35 035
#define OP_SOP36 036
#define OP_SOP37 037
#endif
#define OP_ADD 040
#define OP_ADDU 041
@ -233,73 +304,96 @@ typedef union {
#define OP_SLT 052
#define OP_SLTU 053
#define OP_DADD 054 /* MIPS-II, for r4000 port */
#define OP_DADDU 055 /* MIPS-II, for r4000 port */
#define OP_DSUB 056 /* MIPS-II, for r4000 port */
#define OP_DSUBU 057 /* MIPS-II, for r4000 port */
#define OP_DADD 054
#define OP_DADDU 055
#define OP_DSUB 056
#define OP_DSUBU 057
#define OP_TGE 060 /* MIPS-II, for r4000 port */
#define OP_TGEU 061 /* MIPS-II, for r4000 port */
#define OP_TLT 062 /* MIPS-II, for r4000 port */
#define OP_TLTU 063 /* MIPS-II, for r4000 port */
#define OP_TEQ 064 /* MIPS-II, for r4000 port */
#define OP_TNE 066 /* MIPS-II, for r4000 port */
#define OP_TGE 060
#define OP_TGEU 061
#define OP_TLT 062
#define OP_TLTU 063
#define OP_TEQ 064
#define OP_TNE 066
#define OP_DSLL 070 /* MIPS-II, for r4000 port */
#define OP_DSRL 072 /* MIPS-II, for r4000 port */
#define OP_DSRA 073 /* MIPS-II, for r4000 port */
#define OP_DSLL32 074 /* MIPS-II, for r4000 port */
#define OP_DSRL32 076 /* MIPS-II, for r4000 port */
#define OP_DSRA32 077 /* MIPS-II, for r4000 port */
#define OP_DSLL 070
#define OP_DSRL 072
#define OP_DSRA 073
#define OP_DSLL32 074
#define OP_DSRL32 076
#define OP_DSRA32 077
#if __mips_isa_rev < 6
/*
* Values for the 'func' field when 'op' == OP_SPECIAL2.
* OP_SPECIAL2 opcodes are removed in mips32r6
*/
#define OP_MAD 000 /* QED */
#define OP_MADU 001 /* QED */
#define OP_MUL 002 /* QED */
#endif
/*
* Values for the 'func' field when 'op' == OP_SPECIAL3.
*/
#define OP_EXT 000
#define OP_DEXTM 001
#define OP_DEXTU 002
#define OP_DEXT 003
#define OP_INS 004
#define OP_DINSM 005
#define OP_DINSU 006
#define OP_DINS 007
#define OP_BSHFL 040
#define OP_RDHWR 073
/*
* Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL.
*/
#define OP_WSBH 002
#define OP_SEB 020
#define OP_SEH 030
#if __mips_isa_rev == 6
/*
* Values for the 'shamt' field when OP_SOP30.
*/
#define OP_MUL 002
#define OP_MUH 003
#endif
/*
* Values for the 'func' field when 'op' == OP_BCOND.
*/
#define OP_BLTZ 000
#define OP_BGEZ 001
#define OP_BLTZL 002 /* MIPS-II, for r4000 port */
#define OP_BGEZL 003 /* MIPS-II, for r4000 port */
#define OP_TGEI 010 /* MIPS-II, for r4000 port */
#define OP_TGEIU 011 /* MIPS-II, for r4000 port */
#define OP_TLTI 012 /* MIPS-II, for r4000 port */
#define OP_TLTIU 013 /* MIPS-II, for r4000 port */
#define OP_TEQI 014 /* MIPS-II, for r4000 port */
#define OP_TNEI 016 /* MIPS-II, for r4000 port */
#define OP_BLTZAL 020 /* MIPS-II, for r4000 port */
#if __mips_isa_rev < 6
#define OP_BLTZL 002
#define OP_BGEZL 003
#define OP_TGEI 010
#define OP_TGEIU 011
#define OP_TLTI 012
#define OP_TLTIU 013
#define OP_TEQI 014
#define OP_TNEI 016
#define OP_BLTZAL 020
#define OP_BGEZAL 021
#define OP_BLTZALL 022
#define OP_BGEZALL 023
#else
#define OP_NAL 020
#define OP_BAL 021
#endif
/*
* Values for the 'rs' field when 'op' == OP_COPz.
*/
#define OP_MF 000
#define OP_DMF 001 /* MIPS-II, for r4000 port */
#define OP_DMF 001
#define OP_MT 004
#define OP_DMT 005 /* MIPS-II, for r4000 port */
#define OP_DMT 005
#define OP_BCx 010
#define OP_BCy 014
#define OP_CF 002
@ -311,6 +405,6 @@ typedef union {
#define COPz_BC_TF_MASK 0x01
#define COPz_BC_TRUE 0x01
#define COPz_BC_FALSE 0x00
#define COPz_BCL_TF_MASK 0x02 /* MIPS-II, for r4000 port */
#define COPz_BCL_TRUE 0x02 /* MIPS-II, for r4000 port */
#define COPz_BCL_FALSE 0x00 /* MIPS-II, for r4000 port */
#define COPz_BCL_TF_MASK 0x02
#define COPz_BCL_TRUE 0x02
#define COPz_BCL_FALSE 0x00

View file

@ -42,7 +42,7 @@ inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
#else
inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
#if defined(__mips__) && __mips_isa_rev>=2
uint32_t r;
__asm__("wsbh %0, %1;"
"rotr %0, %0, 16"
@ -55,7 +55,7 @@ inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
#endif
}
inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
#if defined(__mips__) && __mips_isa_rev>=2
uint32_t r;
__asm__("wsbh %0, %1;"
"rotr %0, %0, 16"

View file

@ -520,6 +520,252 @@ inline int64_t gglMulii(int32_t x, int32_t y)
return res;
}
#elif defined(__mips__) && __mips_isa_rev == 6
/*inline MIPS implementations*/
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
GGLfixed result,tmp,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[res], %[a], %[b] \t\n"
: [res]"=&r"(result)
: [a]"r"(a),[b]"r"(b)
);
} else if (shift == 32)
{
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1\t\n"
"sll %[tmp],%[tmp],0x1f\t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"muh %[res], %[a], %[b] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp]\t\n" /*obit*/
"sra %[tmp],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp]\t\n"
"addu %[res],%[res],%[tmp1]\t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
: [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
);
} else if ((shift >0) && (shift < 32))
{
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n"
"sll %[tmp],%[tmp],%[lshift] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"seleqz %[tmp],%[tmp],%[bit5] \t\n"
"selnez %[res],%[res],%[bit5] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"li %[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[shiftm1] \t\n"
"addu %[tmp1],%[tmp],%[res] \t\n"
"sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
"sra %[tmp2],%[tmp],0x1f \t\n"
"addu %[res],%[res],%[tmp] \t\n"
"muh %[tmp], %[a], %[b] \t\n"
"addu %[tmp],%[tmp],%[tmp2] \t\n"
"addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
"srl %[tmp2],%[res],%[rshift] \t\n"
"srav %[res], %[tmp],%[rshift]\t\n"
"sll %[tmp],%[tmp],1 \t\n"
"sll %[tmp],%[tmp],%[norbits] \t\n"
"or %[tmp],%[tmp],%[tmp2] \t\n"
"seleqz %[tmp],%[tmp],%[bit5] \t\n"
"selnez %[res],%[res],%[bit5] \t\n"
"or %[res],%[res],%[tmp] \t\n"
: [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
);
}
return result;
}
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[lo], %[a], %[b] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if (shift == 32) {
asm ("muh %[lo], %[a], %[b] \t\n"
"addu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if ((shift>0) && (shift<32)) {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"addu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
);
}
return result;
}
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
GGLfixed result,t,tmp1,tmp2;
if (__builtin_constant_p(shift)) {
if (shift == 0) {
asm ("mul %[lo], %[a], %[b] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if (shift == 32) {
asm ("muh %[lo], %[a], %[b] \t\n"
"subu %[lo],%[lo],%[c] \t\n"
: [lo]"=&r"(result)
: [a]"r"(a),[b]"r"(b),[c]"r"(c)
);
} else if ((shift>0) && (shift<32)) {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"srl %[res],%[res],%[rshift] \t\n"
"sll %[t],%[t],%[lshift] \t\n"
"or %[res],%[res],%[t] \t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
);
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
);
}
} else {
asm ("mul %[res], %[a], %[b] \t\n"
"muh %[t], %[a], %[b] \t\n"
"nor %[tmp1],$zero,%[shift]\t\n"
"srl %[res],%[res],%[shift] \t\n"
"sll %[tmp2],%[t],1 \t\n"
"sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
"or %[tmp1],%[tmp2],%[res] \t\n"
"srav %[res],%[t],%[shift] \t\n"
"andi %[tmp2],%[shift],0x20\t\n"
"seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
"selnez %[res],%[res],%[tmp2]\t\n"
"or %[res],%[res],%[tmp1]\t\n"
"subu %[res],%[res],%[c] \t\n"
: [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
: [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
);
}
return result;
}
inline int64_t gglMulii(int32_t x, int32_t y) CONST;
inline int64_t gglMulii(int32_t x, int32_t y) {
union {
struct {
#if defined(__MIPSEL__)
int32_t lo;
int32_t hi;
#elif defined(__MIPSEB__)
int32_t hi;
int32_t lo;
#endif
} s;
int64_t res;
}u;
asm("mul %0, %2, %3 \t\n"
"muh %1, %2, %3 \t\n"
: "=r"(u.s.lo), "=&r"(u.s.hi)
: "%r"(x), "r"(y)
);
return u.res;
}
#else // ----------------------------------------------------------------------
inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;

View file

@ -41,6 +41,8 @@
#include "codeflinger/Arm64Assembler.h"
#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#include "codeflinger/MIPSAssembler.h"
#elif defined(__mips__) && defined(__LP64__)
#include "codeflinger/MIPS64Assembler.h"
#endif
//#include "codeflinger/ARMAssemblerOptimizer.h"
@ -59,7 +61,7 @@
# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED
#endif
#if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__)
#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))) || defined(__aarch64__)
# define ANDROID_ARM_CODEGEN 1
#else
# define ANDROID_ARM_CODEGEN 0
@ -73,7 +75,7 @@
*/
#define DEBUG_NEEDS 0
#if defined( __mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#if defined( __mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))
#define ASSEMBLY_SCRATCH_SIZE 4096
#elif defined(__aarch64__)
#define ASSEMBLY_SCRATCH_SIZE 8192
@ -136,6 +138,9 @@ extern "C" void scanline_t32cb16blend_arm64(uint16_t*, uint32_t*, size_t);
extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct);
#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
#elif defined(__mips__) && defined(__LP64__)
extern "C" void scanline_t32cb16blend_mips64(uint16_t*, uint32_t*, size_t);
extern "C" void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t col, size_t ct);
#endif
// ----------------------------------------------------------------------------
@ -286,7 +291,7 @@ static const needs_filter_t fill16noblend = {
#if ANDROID_ARM_CODEGEN
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))
static CodeCache gCodeCache(32 * 1024);
#elif defined(__aarch64__)
static CodeCache gCodeCache(48 * 1024);
@ -406,8 +411,10 @@ static void pick_scanline(context_t* c)
//GGLAssembler assembler(
// new ARMAssemblerOptimizer(new ARMAssembler(a)) );
#endif
#if defined(__mips__)
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
GGLAssembler assembler( new ArmToMipsAssembler(a) );
#elif defined(__mips__) && defined(__LP64__)
GGLAssembler assembler( new ArmToMips64Assembler(a) );
#elif defined(__aarch64__)
GGLAssembler assembler( new ArmToArm64Assembler(a) );
#endif
@ -2103,6 +2110,8 @@ void scanline_col32cb16blend(context_t* c)
#endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN
#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__))
scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct);
#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__mips__) && defined(__LP64__)))
scanline_col32cb16blend_mips64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct);
#else
uint32_t s = GGL_RGBA_TO_HOST(c->packed8888);
int sA = (s>>24);
@ -2175,7 +2184,8 @@ last_one:
void scanline_t32cb16blend(context_t* c)
{
#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__)))
#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || defined(__aarch64__) || \
(defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)))))
int32_t x = c->iterators.xl;
size_t ct = c->iterators.xr - x;
int32_t y = c->iterators.y;
@ -2191,8 +2201,10 @@ void scanline_t32cb16blend(context_t* c)
scanline_t32cb16blend_arm(dst, src, ct);
#elif defined(__aarch64__)
scanline_t32cb16blend_arm64(dst, src, ct);
#elif defined(__mips__)
#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
scanline_t32cb16blend_mips(dst, src, ct);
#elif defined(__mips__) && defined(__LP64__)
scanline_t32cb16blend_mips64(dst, src, ct);
#endif
#else
dst_iterator16 di(c);

View file

@ -0,0 +1,6 @@
ifeq ($(TARGET_ARCH),mips)
include $(all-subdir-makefiles)
endif
ifeq ($(TARGET_ARCH),mipsel)
include $(all-subdir-makefiles)
endif

View file

@ -0,0 +1,18 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
col32cb16blend_test.c \
../../../arch-mips/col32cb16blend.S
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES :=
LOCAL_MODULE:= test-pixelflinger-mips-col32cb16blend
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := 32
include $(BUILD_NATIVE_TEST)

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define ARGB_8888_MAX 0xFFFFFFFF
#define ARGB_8888_MIN 0x00000000
#define RGB_565_MAX 0xFFFF
#define RGB_565_MIN 0x0000
struct test_t
{
char name[256];
uint32_t src_color;
uint16_t dst_color;
size_t count;
};
struct test_t tests[] =
{
{"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
{"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
{"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
{"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
{"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
{"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
{"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
{"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
{"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
{"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
};
void scanline_col32cb16blend_mips(uint16_t *dst, uint32_t src, size_t count);
void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
{
uint32_t srcAlpha = (src>>24);
uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
while (count--)
{
uint16_t d = *dst;
int dstR = (d>>11)&0x1f;
int dstG = (d>>5)&0x3f;
int dstB = (d)&0x1f;
int srcR = (src >> ( 3))&0x1F;
int srcG = (src >> ( 8+2))&0x3F;
int srcB = (src >> (16+3))&0x1F;
srcR += (f*dstR)>>8;
srcG += (f*dstG)>>8;
srcB += (f*dstB)>>8;
*dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
}
}
void scanline_col32cb16blend_test()
{
uint16_t dst_c[16], dst_asm[16];
uint32_t i, j;
for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
{
struct test_t test = tests[i];
printf("Testing - %s:",test.name);
memset(dst_c, 0, sizeof(dst_c));
memset(dst_asm, 0, sizeof(dst_asm));
for(j = 0; j < test.count; ++j)
{
dst_c[j] = test.dst_color;
dst_asm[j] = test.dst_color;
}
scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
scanline_col32cb16blend_mips(dst_asm, test.src_color, test.count);
if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
printf("Passed\n");
else
printf("Failed\n");
for(j = 0; j < test.count; ++j)
{
printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
}
}
}
int main()
{
scanline_col32cb16blend_test();
return 0;
}

View file

@ -0,0 +1,18 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
t32cb16blend_test.c \
../../../arch-mips/t32cb16blend.S
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES :=
LOCAL_MODULE:= test-pixelflinger-mips-t32cb16blend
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := 32
include $(BUILD_NATIVE_TEST)

View file

@ -0,0 +1,134 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define ARGB_8888_MAX 0xFFFFFFFF
#define ARGB_8888_MIN 0x00000000
#define RGB_565_MAX 0xFFFF
#define RGB_565_MIN 0x0000
struct test_t
{
char name[256];
uint32_t src_color;
uint16_t dst_color;
size_t count;
};
struct test_t tests[] =
{
{"Count 0", 0, 0, 0},
{"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
{"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
{"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
{"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
{"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
{"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
{"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
{"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
{"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
{"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
};
void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count)
{
while (count--)
{
uint16_t d = *dst;
uint32_t s = *src++;
int dstR = (d>>11)&0x1f;
int dstG = (d>>5)&0x3f;
int dstB = (d)&0x1f;
int srcR = (s >> ( 3))&0x1F;
int srcG = (s >> ( 8+2))&0x3F;
int srcB = (s >> (16+3))&0x1F;
int srcAlpha = (s>>24) & 0xFF;
int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1));
srcR += (f*dstR)>>8;
srcG += (f*dstG)>>8;
srcB += (f*dstB)>>8;
// srcR = srcR > 0x1F? 0x1F: srcR;
// srcG = srcG > 0x3F? 0x3F: srcG;
// srcB = srcB > 0x1F? 0x1F: srcB;
*dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
}
}
void scanline_t32cb16blend_test()
{
uint16_t dst_c[16], dst_asm[16];
uint32_t src[16];
uint32_t i;
uint32_t j;
for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
{
struct test_t test = tests[i];
printf("Testing - %s:",test.name);
memset(dst_c, 0, sizeof(dst_c));
memset(dst_asm, 0, sizeof(dst_asm));
for(j = 0; j < test.count; ++j)
{
dst_c[j] = test.dst_color;
dst_asm[j] = test.dst_color;
src[j] = test.src_color;
}
scanline_t32cb16blend_c(dst_c,src,test.count);
scanline_t32cb16blend_mips(dst_asm,src,test.count);
if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
printf("Passed\n");
else
printf("Failed\n");
for(j = 0; j < test.count; ++j)
{
printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
}
}
}
int main()
{
scanline_t32cb16blend_test();
return 0;
}

View file

@ -0,0 +1,3 @@
ifeq ($(TARGET_ARCH),mips64)
include $(all-subdir-makefiles)
endif

View file

@ -0,0 +1,21 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
mips64_assembler_test.cpp\
asm_mips_test_jacket.S
LOCAL_SHARED_LIBRARIES := \
libcutils \
libpixelflinger
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/../../..
LOCAL_MODULE:= test-pixelflinger-mips64-assembler-test
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := 64
include $(BUILD_NATIVE_TEST)

View file

@ -0,0 +1,93 @@
# /*
# * Copyright (C) 2015 The Android Open Source Project
# * All rights reserved.
# *
# * Redistribution and use in source and binary forms, with or without
# * modification, are permitted provided that the following conditions
# * are met:
# * * Redistributions of source code must retain the above copyright
# * notice, this list of conditions and the following disclaimer.
# * * Redistributions in binary form must reproduce the above copyright
# * notice, this list of conditions and the following disclaimer in
# * the documentation and/or other materials provided with the
# * distribution.
# *
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# * SUCH DAMAGE.
# */
.text
.align 8
.global asm_mips_test_jacket
# // Set the register
# // Calls the asm function
# // Reads the register values to output register
# // Parameters
# // a0 - Function to jump
# // a1 - register values array
# // a2 - flag values array
asm_mips_test_jacket:
# // Save registers to stack
daddiu $sp, $sp, -96
sd $s0, 64($sp)
sd $s1, 72($sp)
sd $s2, 80($sp)
sd $ra, 88($sp)
move $s0, $a0
move $s1, $a1
move $s2, $a2
ld $v0, 16($s1)
ld $v1, 24($s1)
ld $a0, 32($s1)
ld $a1, 40($s1)
ld $a2, 48($s1)
ld $a3, 56($s1)
ld $a4, 64($s1)
ld $a5, 72($s1)
ld $a6, 80($s1)
ld $a7, 88($s1)
ld $t0, 96($s1)
ld $t1, 104($s1)
ld $t2, 112($s1)
ld $t3, 120($s1)
jal $s0
sd $v0, 16($s1)
sd $v1, 24($s1)
sd $a0, 32($s1)
sd $a1, 40($s1)
sd $a2, 48($s1)
sd $a3, 56($s1)
sd $a4, 64($s1)
sd $a5, 72($s1)
sd $a6, 80($s1)
sd $a7, 88($s1)
sd $t0, 96($s1)
sd $t1, 104($s1)
sd $t2, 112($s1)
sd $t3, 120($s1)
ld $s0, 64($sp)
ld $s1, 72($sp)
ld $s2, 80($sp)
ld $ra, 88($sp)
daddiu $sp, $sp, 96
j $ra

View file

@ -0,0 +1,644 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>
#include <cutils/atomic.h>
#include <cutils/log.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "codeflinger/ARMAssemblerInterface.h"
#include "codeflinger/MIPS64Assembler.h"
using namespace android;
#define TESTS_DATAOP_ENABLE 1
#define TESTS_DATATRANSFER_ENABLE 1
#define ASSEMBLY_SCRATCH_SIZE 4096
void *instrMem;
uint32_t instrMemSize = 128 * 1024;
char dataMem[8192];
typedef void (*asm_function_t)();
extern "C" void asm_mips_test_jacket(asm_function_t function,
int64_t regs[], int32_t flags[]);
#define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1)
#define MAX_64BIT ((uint64_t)0xFFFFFFFFFFFFFFFF)
const uint32_t NA = 0;
const uint32_t NUM_REGS = 32;
const uint32_t NUM_FLAGS = 16;
enum instr_t
{
INSTR_ADD,
INSTR_SUB,
INSTR_AND,
INSTR_ORR,
INSTR_RSB,
INSTR_BIC,
INSTR_CMP,
INSTR_MOV,
INSTR_MVN,
INSTR_MUL,
INSTR_MLA,
INSTR_SMULBB,
INSTR_SMULBT,
INSTR_SMULTB,
INSTR_SMULTT,
INSTR_SMULWB,
INSTR_SMULWT,
INSTR_SMLABB,
INSTR_UXTB16,
INSTR_UBFX,
INSTR_ADDR_ADD,
INSTR_ADDR_SUB,
INSTR_LDR,
INSTR_LDRB,
INSTR_LDRH,
INSTR_ADDR_LDR,
INSTR_LDM,
INSTR_STR,
INSTR_STRB,
INSTR_STRH,
INSTR_ADDR_STR,
INSTR_STM
};
enum shift_t
{
SHIFT_LSL,
SHIFT_LSR,
SHIFT_ASR,
SHIFT_ROR,
SHIFT_NONE
};
enum offset_t
{
REG_SCALE_OFFSET,
REG_OFFSET,
IMM8_OFFSET,
IMM12_OFFSET,
NO_OFFSET
};
enum cond_t
{
EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
HS = CS,
LO = CC
};
const char * cc_code[] =
{
"EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
"HI", "LS","GE","LT", "GT", "LE", "AL", "NV"
};
struct condTest_t
{
int mode;
int32_t Rcond1;
int32_t Rcond2;
uint64_t Rcond1Value;
uint64_t Rcond2Value;
};
struct dataOpTest_t
{
uint32_t id;
instr_t op;
condTest_t preCond;
cond_t cond;
bool setFlags;
uint64_t RnValue;
uint64_t RsValue;
bool immediate;
uint32_t immValue;
uint64_t RmValue;
uint32_t shiftMode;
uint32_t shiftAmount;
uint64_t RdValue;
bool checkRd;
uint64_t postRdValue;
};
struct dataTransferTest_t
{
uint32_t id;
instr_t op;
uint32_t preFlag;
cond_t cond;
bool setMem;
uint64_t memOffset;
uint64_t memValue;
uint64_t RnValue;
offset_t offsetType;
uint64_t RmValue;
uint32_t immValue;
bool writeBack;
bool preIndex;
bool postIndex;
uint64_t RdValue;
uint64_t postRdValue;
uint64_t postRnValue;
bool checkMem;
uint64_t postMemOffset;
uint32_t postMemLength;
uint64_t postMemValue;
};
dataOpTest_t dataOpTests [] =
{
{0xA000,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
{0xA001,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,MAX_64BIT},
{0xA002,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,NA,NA,NA,1,0},
{0xA003,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT-1,NA,NA,NA,1,MAX_64BIT},
{0xA004,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL, 0,NA,1,0},
{0xA005,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
{0xA006,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2},
{0xA007,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,2},
{0xA008,INSTR_ADD,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
{0xA009,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
{0xA010,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,0,0,0,NA,1,1},
{0xA011,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,0,0,0,NA,1,0},
{0xA012,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,1},
{0xA013,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,0},
{0xA014,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,1},
{0xA015,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0},
{0xA016,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
{0xA017,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
{0xA018,INSTR_AND,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0},
{0xA019,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_ASR,31,NA,1,1},
{0xA020,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,1,MAX_32BIT,0,0,0,NA,1,MAX_64BIT},
{0xA021,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,1,MAX_32BIT-1,0,0,0,NA,1,MAX_64BIT-1},
{0xA022,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,0,0,MAX_32BIT,0,0,NA,1,MAX_64BIT},
{0xA023,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,0,0,MAX_32BIT-1,0,0,NA,1,MAX_64BIT-1},
{0xA024,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,MAX_64BIT},
{0xA025,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
{0xA026,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
{0xA027,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
{0xA028,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
{0xA029,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,MAX_64BIT},
{0xA030,INSTR_CMP,{0,0,0,0,0},AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0},
{0xA031,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0},
{0xA032,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000},
{0xA033,INSTR_MUL,{0,0,0,0,0},AL,0,0,MAX_32BIT,0,0,1,0,0,NA,1,MAX_64BIT},
{0xA034,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000},
{0xA035,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000},
{0xA036,INSTR_SUB,{1,R_v1,R_a6,2,4},MI,0,2,NA,0,NA,1,NA,NA,2,1,1},
{0xA037,INSTR_SUB,{2,R_v1,R_a6,2,0},MI,0,2,NA,0,NA,1,NA,NA,2,1,2},
{0xA038,INSTR_SUB,{1,R_v1,R_a6,4,2},GE,0,2,NA,1,1,NA,NA,NA,2,1,1},
{0xA039,INSTR_SUB,{1,R_a5,R_a6,2,7},GE,0,2,NA,1,1,NA,NA,NA,2,1,2},
{0xA040,INSTR_SUB,{1,R_a5,R_a6,1,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,1},
{0xA041,INSTR_SUB,{1,R_a5,R_a6,0,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,2},
{0xA042,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1<< 16,0,0,0,NA,1,(uint64_t)(1 -(1<<16))},
{0xA043,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_64BIT-1},
{0xA044,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1,0,0,0,NA,1,0},
{0xA045,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(uint64_t)(1 -(1<<16))},
{0xA046,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_64BIT-1},
{0xA047,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
{0xA048,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(uint64_t)(1 -(1<<16))},
{0xA049,INSTR_SUB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT,SHIFT_LSL,31,NA,1,1},
{0xA050,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
{0xA051,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
{0xA052,INSTR_RSB,{1,R_a5,R_a6,4,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,(uint64_t)-2},
{0xA053,INSTR_RSB,{1,R_a5,R_a6,-1,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,2},
{0xA054,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1<<16,NA,NA,NA,NA,1,(1<<16)-1},
{0xA055,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,NA,NA,NA,NA,1,(uint64_t)(1-MAX_64BIT)},
{0xA056,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1,NA,NA,NA,NA,1,0},
{0xA057,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(1<<16)-1},
{0xA058,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,(uint64_t)(1-MAX_64BIT)},
{0xA059,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
{0xA060,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1<<16)-1},
{0xA061,INSTR_RSB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,(uint64_t)(-1)},
{0xA062,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
{0xA063,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
{0xA064,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0xFFFFFFFF80000001},
{0xA065,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0xFFFFFFFF80000001},
{0xA066,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,NA,1,MAX_64BIT-1},
{0xA067,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000000},
{0xA068,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
{0xA069,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
{0xA070,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
{0xA071,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_64BIT ,SHIFT_ASR,31,NA,1,MAX_64BIT},
{0xA072,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0xFFFFFFFF80000001},
{0xA073,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3},
{0xA074,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,MAX_64BIT -1,SHIFT_ASR,1,NA,1,MAX_64BIT},
{0xA075,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
{0xA076,INSTR_MOV,{2,R_a5,R_a6,6,8},MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
{0xA077,INSTR_MOV,{2,R_a5,R_a6,-4,-8},MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
{0xA078,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
{0xA079,INSTR_MOV,{1,R_a5,R_a6,-1,1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
{0xA080,INSTR_MOV,{1,R_a5,R_a6,-1,-5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
{0xA081,INSTR_MOV,{1,R_a5,R_a6,5,5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
{0xA082,INSTR_MOV,{1,R_a5,R_a6,-1,1},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,2},
{0xA083,INSTR_MOV,{1,R_a5,R_a6,4,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
{0xA084,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
{0xA085,INSTR_MOV,{1,R_a5,R_a6,-1,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
{0xA086,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
{0xA087,INSTR_MOV,{1,R_a5,R_a6,-1,-3},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
{0xA088,INSTR_MOV,{1,R_a5,R_a6,-1,0},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
{0xA089,INSTR_MOV,{1,R_a5,R_a6,-1,-1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
{0xA090,INSTR_MOV,{1,R_a5,R_a6,6,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
{0xA091,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
{0xA092,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
{0xA093,INSTR_MOV,{1,R_a5,R_a6,4,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1},
{0xA094,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2},
{0xA095,INSTR_MOV,{1,R_a5,R_a6,1,-1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
{0xA096,INSTR_MOV,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
{0xA097,INSTR_MVN,{1,R_a5,R_a6,1,4},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,2},
{0xA098,INSTR_MVN,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,1},
{0xA099,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_64BIT},
{0xA100,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,MAX_32BIT-1,NA,0,2,1,1},
{0xA101,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE},
{0xA102,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
{0xA103,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,1},
{0xA104,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,0},
{0xA105,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,1},
{0xA106,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0},
{0xA107,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
{0xA108,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA109,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
{0xA110,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA111,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
{0xA112,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA113,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
{0xA114,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA115,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
{0xA116,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA117,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
{0xA118,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA119,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
{0xA120,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA121,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
{0xA122,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA123,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
{0xA124,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
{0xA125,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
{0xA126,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA127,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
{0xA128,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
{0xA129,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
{0xA130,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
{0xA131,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
{0xA132,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0},
{0xA133,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00001000},
{0xA134,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
{0xA135,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0},
{0xA136,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001},
{0xA137,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF},
{0xA138,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD},
{0xA139,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB},
{0xA140,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001},
{0xA141,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5},
{0xA142,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000},
{0xA143,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF},
{0xA144,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB},
{0xA145,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1},
};
dataTransferTest_t dataTransferTests [] =
{
{0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA},
{0xB001,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA},
{0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA},
{0xB003,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA},
{0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA},
{0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA},
{0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA},
{0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA},
{0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA},
{0xB009,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA},
{0xB010,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA},
{0xB011,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA},
{0xB012,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA},
{0xB013,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA},
{0xB014,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF},
{0xB015,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF},
{0xB016,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
{0xB017,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF},
{0xB018,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF},
{0xB019,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF},
{0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
{0xB021,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM8_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF},
{0xB022,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
};
void flushcache()
{
const long base = long(instrMem);
const long curr = base + long(instrMemSize);
__builtin___clear_cache((char*)base, (char*)curr);
}
void dataOpTest(dataOpTest_t test, ArmToMips64Assembler *a64asm, uint32_t Rd = R_v1,
uint32_t Rn = R_t0, uint32_t Rm = R_t1, uint32_t Rs = R_t2)
{
int64_t regs[NUM_REGS] = {0};
int32_t flags[NUM_FLAGS] = {0};
int64_t savedRegs[NUM_REGS] = {0};
uint32_t i;
uint32_t op2;
for(i = 0; i < NUM_REGS; ++i)
{
regs[i] = i;
}
regs[Rd] = test.RdValue;
regs[Rn] = test.RnValue;
regs[Rs] = test.RsValue;
a64asm->reset();
if (test.preCond.mode) {
a64asm->set_condition(test.preCond.mode, test.preCond.Rcond1, test.preCond.Rcond2);
regs[test.preCond.Rcond1] = test.preCond.Rcond1Value;
regs[test.preCond.Rcond2] = test.preCond.Rcond2Value;
}
a64asm->prolog();
if(test.immediate == true)
{
op2 = a64asm->imm(test.immValue);
}
else if(test.immediate == false && test.shiftAmount == 0)
{
op2 = Rm;
regs[Rm] = (int64_t)((int32_t)(test.RmValue));
}
else
{
op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount);
regs[Rm] = (int64_t)((int32_t)(test.RmValue));
}
switch(test.op)
{
case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break;
case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break;
case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break;
case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break;
case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break;
case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break;
case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break;
case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break;
case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break;
case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
default: printf("Error"); return;
}
a64asm->epilog(0);
a64asm->fix_branches();
flushcache();
asm_function_t asm_function = (asm_function_t)(instrMem);
for(i = 0; i < NUM_REGS; ++i)
savedRegs[i] = regs[i];
asm_mips_test_jacket(asm_function, regs, flags);
/* Check if all regs except Rd is same */
for(i = 0; i < NUM_REGS; ++i)
{
if((i == Rd) || i == 2) continue;
if(regs[i] != savedRegs[i])
{
printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 "),"
"Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i],
regs[i]);
exit(0);
return;
}
}
if(test.checkRd == 1 && regs[Rd] != test.postRdValue)
{
printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n",
test.id, test.postRdValue, regs[Rd]);
exit(0);
}
else
{
printf("Test %x passed\n", test.id);
}
}
void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm,
uint32_t Rd = R_v1, uint32_t Rn = R_t0,uint32_t Rm = R_t1)
{
int64_t regs[NUM_REGS] = {0};
int64_t savedRegs[NUM_REGS] = {0};
int32_t flags[NUM_FLAGS] = {0};
uint32_t i;
for(i = 0; i < NUM_REGS; ++i)
{
regs[i] = i;
}
uint32_t op2;
regs[Rd] = test.RdValue;
regs[Rn] = (uint64_t)(&dataMem[test.RnValue]);
regs[Rm] = test.RmValue;
flags[test.preFlag] = 1;
if(test.setMem == true)
{
unsigned char *mem = (unsigned char *)&dataMem[test.memOffset];
uint64_t value = test.memValue;
for(int j = 0; j < 8; ++j)
{
mem[j] = value & 0x00FF;
value >>= 8;
}
}
a64asm->reset();
a64asm->prolog();
if(test.offsetType == REG_SCALE_OFFSET)
{
op2 = a64asm->reg_scale_pre(Rm);
}
else if(test.offsetType == REG_OFFSET)
{
op2 = a64asm->reg_pre(Rm);
}
else if(test.offsetType == IMM12_OFFSET && test.preIndex == true)
{
op2 = a64asm->immed12_pre(test.immValue, test.writeBack);
}
else if(test.offsetType == IMM12_OFFSET && test.postIndex == true)
{
op2 = a64asm->immed12_post(test.immValue);
}
else if(test.offsetType == IMM8_OFFSET && test.preIndex == true)
{
op2 = a64asm->immed8_pre(test.immValue, test.writeBack);
}
else if(test.offsetType == IMM8_OFFSET && test.postIndex == true)
{
op2 = a64asm->immed8_post(test.immValue);
}
else if(test.offsetType == NO_OFFSET)
{
op2 = a64asm->__immed12_pre(0);
}
else
{
printf("Error - Unknown offset\n"); return;
}
switch(test.op)
{
case INSTR_LDR: a64asm->LDR(test.cond, Rd,Rn,op2); break;
case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break;
case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break;
case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break;
case INSTR_STR: a64asm->STR(test.cond, Rd,Rn,op2); break;
case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break;
case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break;
case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break;
default: printf("Error"); return;
}
a64asm->epilog(0);
flushcache();
asm_function_t asm_function = (asm_function_t)(instrMem);
for(i = 0; i < NUM_REGS; ++i)
savedRegs[i] = regs[i];
asm_mips_test_jacket(asm_function, regs, flags);
/* Check if all regs except Rd/Rn are same */
for(i = 0; i < NUM_REGS; ++i)
{
if(i == Rd || i == Rn || i == R_v0) continue;
if(regs[i] != savedRegs[i])
{
printf("Test %x failed Reg(%d) tampered"
" Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n",
test.id, i, savedRegs[i], regs[i]);
return;
}
}
if((uint64_t)regs[Rd] != test.postRdValue)
{
printf("Test %x failed, "
"Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postRdValue, regs[Rd]);
}
else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue]))
{
printf("Test %x failed, "
"Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem);
}
else if(test.checkMem == true)
{
unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset];
uint64_t value;
value = 0;
for(uint32_t j = 0; j < test.postMemLength; ++j)
value = (value << 8) | addr[test.postMemLength-j-1];
if(value != test.postMemValue)
{
printf("Test %x failed, "
"Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
test.id, test.postMemValue, value);
}
else
{
printf("Test %x passed\n", test.id);
}
}
else
{
printf("Test %x passed\n", test.id);
}
}
int main(void)
{
uint32_t i;
/* Allocate memory to store instructions generated by ArmToArm64Assembler */
{
int fd = ashmem_create_region("code cache", instrMemSize);
if(fd < 0) {
printf("IF < 0\n");
printf("Creating code cache, ashmem_create_region "
"failed with error '%s'", strerror(errno));
}
instrMem = mmap(NULL, instrMemSize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE, fd, 0);
}
ArmToMips64Assembler a64asm(instrMem);
if(TESTS_DATAOP_ENABLE)
{
printf("Running data processing tests\n");
for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i) {
dataOpTest(dataOpTests[i], &a64asm);
}
}
if(TESTS_DATATRANSFER_ENABLE)
{
printf("Running data transfer tests\n");
for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i)
dataTransferTest(dataTransferTests[i], &a64asm);
}
return 0;
}

View file

@ -0,0 +1,18 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
col32cb16blend_test.c \
../../../arch-mips64/col32cb16blend.S
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES :=
LOCAL_MODULE:= test-pixelflinger-mips64-col32cb16blend
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := 64
include $(BUILD_NATIVE_TEST)

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define ARGB_8888_MAX 0xFFFFFFFF
#define ARGB_8888_MIN 0x00000000
#define RGB_565_MAX 0xFFFF
#define RGB_565_MIN 0x0000
struct test_t
{
char name[256];
uint32_t src_color;
uint16_t dst_color;
size_t count;
};
struct test_t tests[] =
{
{"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
{"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
{"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
{"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
{"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
{"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
{"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
{"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
{"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
{"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
};
void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t src, size_t count);
void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
{
uint32_t srcAlpha = (src>>24);
uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
while (count--)
{
uint16_t d = *dst;
int dstR = (d>>11)&0x1f;
int dstG = (d>>5)&0x3f;
int dstB = (d)&0x1f;
int srcR = (src >> ( 3))&0x1F;
int srcG = (src >> ( 8+2))&0x3F;
int srcB = (src >> (16+3))&0x1F;
srcR += (f*dstR)>>8;
srcG += (f*dstG)>>8;
srcB += (f*dstB)>>8;
*dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
}
}
void scanline_col32cb16blend_test()
{
uint16_t dst_c[16], dst_asm[16];
uint32_t i, j;
for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
{
struct test_t test = tests[i];
printf("Testing - %s:",test.name);
memset(dst_c, 0, sizeof(dst_c));
memset(dst_asm, 0, sizeof(dst_asm));
for(j = 0; j < test.count; ++j)
{
dst_c[j] = test.dst_color;
dst_asm[j] = test.dst_color;
}
scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
scanline_col32cb16blend_mips64(dst_asm, test.src_color, test.count);
if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
printf("Passed\n");
else
printf("Failed\n");
for(j = 0; j < test.count; ++j)
{
printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
}
}
}
int main()
{
scanline_col32cb16blend_test();
return 0;
}

View file

@ -0,0 +1,16 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
mips64_disassembler_test.cpp \
../../../codeflinger/mips64_disassem.c
LOCAL_SHARED_LIBRARIES :=
LOCAL_MODULE:= test-pixelflinger-mips64-disassembler-test
LOCAL_MODULE_TAGS := tests
LOCAL_MULTILIB := 64
include $(BUILD_NATIVE_TEST)

View file

@ -0,0 +1,218 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include "../../../codeflinger/mips64_disassem.h"
//typedef uint64_t db_addr_t;
//db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_format);
struct test_table_entry_t
{
uint32_t code;
const char *instr;
};
static test_table_entry_t test_table [] =
{
{ 0x00011020, "add\tv0,zero,at" },
{ 0x00832820, "add\ta1,a0,v1" },
{ 0x00c74020, "add\ta4,a2,a3" },
{ 0x012a5820, "add\ta7,a5,a6" },
{ 0x258dffff, "addiu\tt1,t0,-1" },
{ 0x25cf0004, "addiu\tt3,t2,4" },
{ 0x02119021, "addu\ts2,s0,s1" },
{ 0x0274a821, "addu\ts5,s3,s4" },
{ 0x02d7c024, "and\tt8,s6,s7" },
{ 0x333aff00, "andi\tk0,t9,0xff00" },
{ 0x3f7cffff, "aui\tgp,k1,-1" },
{ 0x3c1dffff, "lui\tsp,0xffff" },
{ 0x00e04051, "clo\ta4,a3" },
{ 0x01205050, "clz\ta6,a5" },
{ 0x016c682c, "dadd\tt1,a7,t0" },
{ 0x65cf0008, "daddiu\tt3,t2,8" },
{ 0x0211902d, "daddu\ts2,s0,s1" },
{ 0x7e741403, "dext\ts4,s3,16,3" },
{ 0x7eb6f801, "dextm\ts6,s5,0,64" },
{ 0x7ef87c02, "dextu\tt8,s7,48,16" },
{ 0x7f3a8207, "dins\tk0,t9,8,9" },
{ 0x7f7c0005, "dinsm\tgp,k1,0,33" },
{ 0x7fbe0806, "dinsu\ts8,sp,32,2" },
{ 0x03e1102e, "dsub\tv0,ra,at" },
{ 0x0064282f, "dsubu\ta1,v1,a0" },
{ 0x7cc77a00, "ext\ta3,a2,8,16" },
{ 0x7d09fc04, "ins\ta5,a4,16,16" },
{ 0x00200009, "jr\tat" },
{ 0x00201009, "jalr\tv0,at" },
{ 0x0020f809, "jalr\tat" },
{ 0x8082fff0, "lb\tv0,-16(a0)" },
{ 0x916c0008, "lbu\tt0,8(a7)" },
{ 0xdfa3ffe8, "ld\tv1,-24(sp)" },
{ 0x84850080, "lh\ta1,128(a0)" },
{ 0x94c7ff80, "lhu\ta3,-128(a2)" },
{ 0x8d09000c, "lw\ta5,12(a4)" },
{ 0x9d4bfff4, "lwu\ta7,-12(a6)" },
{ 0x00620898, "mul\tat,v1,v0" },
{ 0x006208d8, "muh\tat,v1,v0" },
{ 0x00620899, "mulu\tat,v1,v0" },
{ 0x006208d9, "muhu\tat,v1,v0" },
{ 0x00000000, "nop" },
{ 0x02329827, "nor\ts3,s1,s2" },
{ 0x0295b025, "or\ts6,s4,s5" },
{ 0x36f0ff00, "ori\ts0,s7,0xff00" },
{ 0x7c03103b, "rdhwr\tv0,v1" },
{ 0x00242a02, "rotr\ta1,a0,8" },
{ 0x00c74046, "rotrv\ta4,a3,a2" },
{ 0xa12afff0, "sb\ta6,-16(a5)" },
{ 0xfd6c0100, "sd\tt0,256(a7)" },
{ 0x7c0d7420, "seb\tt2,t1" },
{ 0x7c0f8620, "seh\ts0,t3" },
{ 0x02329835, "seleqz\ts3,s1,s2" },
{ 0x0295b037, "selnez\ts6,s4,s5" },
{ 0xa6f84000, "sh\tt8,16384(s7)" },
{ 0x0019d100, "sll\tk0,t9,4" },
{ 0x037ce804, "sllv\tsp,gp,k1" },
{ 0x03df082a, "slt\tat,s8,ra" },
{ 0x28430007, "slti\tv1,v0,7" },
{ 0x2c850020, "sltiu\ta1,a0,32" },
{ 0x00c7402b, "sltu\ta4,a2,a3" },
{ 0x00095103, "sra\ta6,a5,4" },
{ 0x016c6807, "srav\tt1,t0,a7" },
{ 0x000e7a02, "srl\tt3,t2,8" },
{ 0x02119006, "srlv\ts2,s1,s0" },
{ 0x0274a822, "sub\ts5,s3,s4" },
{ 0x02d7c023, "subu\tt8,s6,s7" },
{ 0xaf3afffc, "sw\tk0,-4(t9)" },
{ 0x7c1be0a0, "wsbh\tgp,k1" },
{ 0x03bef826, "xor\tra,sp,s8" },
{ 0x3801ffff, "li\tat,0xffff" },
{ 0x3843ffff, "xori\tv1,v0,0xffff" },
};
struct test_branches_table_entry_t
{
uint32_t code;
const char *instr;
int16_t offset;
};
static test_branches_table_entry_t test_branches_table [] = {
{ 0x1000ffff, "b\t", 0xffff },
{ 0x13df0008, "beq\ts8,ra,", 0x8 },
{ 0x042100ff, "bgez\tat,", 0xff },
{ 0x1c40ff00, "bgtz\tv0,", 0xff00 },
{ 0x18605555, "blez\tv1,", 0x5555 },
{ 0x0480aaaa, "bltz\ta0,", 0xaaaa },
{ 0x14a68888, "bne\ta1,a2,", 0x8888 },
};
struct test_jump_table_entry_t
{
uint32_t code;
const char *instr;
int32_t offset;
};
static test_jump_table_entry_t test_jump_table [] = {
{ 0x0956ae66, "j\t", 0x156ae66 },
{ 0x0d56ae66, "jal\t", 0x156ae66 },
};
int main()
{
char instr[256];
uint32_t failed = 0;
for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
{
test_table_entry_t *test;
test = &test_table[i];
mips_disassem(&test->code, instr, 0);
if(strcmp(instr, test->instr) != 0)
{
printf("Test Failed \n"
"Code : 0x%0x\n"
"Expected : %s\n"
"Actual : %s\n", test->code, test->instr, instr);
failed++;
}
}
for(uint32_t i = 0; i < sizeof(test_branches_table)/sizeof(test_branches_table_entry_t); ++i)
{
test_branches_table_entry_t *test;
test = &test_branches_table[i];
mips_disassem(&test->code, instr, 0);
//printf("DBG code address: %lx\n", (uint64_t)(&test->code));
uint64_t loc = (uint64_t)test + 4 + (test->offset << 2);
//printf("DBG loc: %lx\n", loc);
char temp[256], address[16];
strcpy(temp, test->instr);
sprintf(address, "0x%lx", loc);
strcat(temp, address);
if(strcmp(instr, temp) != 0)
{
printf("Test Failed \n"
"Code : 0x%0x\n"
"Expected : %s\n"
"Actual : %s\n", test->code, temp, instr);
failed++;
}
}
for(uint32_t i = 0; i < sizeof(test_jump_table)/sizeof(test_jump_table_entry_t); ++i)
{
test_jump_table_entry_t *test;
test = &test_jump_table[i];
mips_disassem(&test->code, instr, 0);
//printf("DBG code address: %lx\n", (uint64_t)(&test->code));
uint64_t loc = ((uint64_t)test & 0xfffffffff0000000) | (test->offset << 2);
//printf("DBG loc: %lx\n", loc);
char temp[256], address[16];
strcpy(temp, test->instr);
sprintf(address, "0x%08lx", loc);
strcat(temp, address);
if(strcmp(instr, temp) != 0)
{
printf("Test Failed \n"
"Code : 0x%0x\n"
"Expected : '%s'\n"
"Actual : '%s'\n", test->code, temp, instr);
failed++;
}
}
if(failed == 0)
{
printf("All tests PASSED\n");
return 0;
}
else
{
printf("%d tests FAILED\n", failed);
return -1;
}
}

View file

@ -11,16 +11,18 @@
#include "codeflinger/ARMAssembler.h"
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#include "codeflinger/MIPSAssembler.h"
#elif defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
#include "codeflinger/MIPS64Assembler.h"
#endif
#include "codeflinger/Arm64Assembler.h"
#if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__)
#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))) || defined(__aarch64__)
# define ANDROID_ARM_CODEGEN 1
#else
# define ANDROID_ARM_CODEGEN 0
#endif
#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))
#define ASSEMBLY_SCRATCH_SIZE 4096
#elif defined(__aarch64__)
#define ASSEMBLY_SCRATCH_SIZE 8192
@ -58,6 +60,10 @@ static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1)
GGLAssembler assembler( new ArmToMipsAssembler(a) );
#endif
#if defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
GGLAssembler assembler( new ArmToMips64Assembler(a) );
#endif
#if defined(__aarch64__)
GGLAssembler assembler( new ArmToArm64Assembler(a) );
#endif