summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libpixelflinger/Android.mk9
-rw-r--r--libpixelflinger/arch-mips/col32cb16blend.S134
-rw-r--r--libpixelflinger/arch-mips/t32cb16blend.S373
-rw-r--r--libpixelflinger/arch-mips64/col32cb16blend.S108
-rw-r--r--libpixelflinger/arch-mips64/t32cb16blend.S172
-rw-r--r--libpixelflinger/codeflinger/ARMAssemblerInterface.h5
-rw-r--r--libpixelflinger/codeflinger/GGLAssembler.cpp9
-rw-r--r--libpixelflinger/codeflinger/MIPS64Assembler.cpp1452
-rw-r--r--libpixelflinger/codeflinger/MIPS64Assembler.h429
-rw-r--r--libpixelflinger/codeflinger/MIPSAssembler.cpp4
-rw-r--r--libpixelflinger/codeflinger/MIPSAssembler.h30
-rw-r--r--libpixelflinger/codeflinger/mips64_disassem.c582
-rw-r--r--libpixelflinger/codeflinger/mips64_disassem.h56
-rw-r--r--libpixelflinger/codeflinger/mips_disassem.c8
-rw-r--r--libpixelflinger/codeflinger/mips_opcode.h220
-rw-r--r--libpixelflinger/include/private/pixelflinger/ggl_context.h4
-rw-r--r--libpixelflinger/include/private/pixelflinger/ggl_fixed.h246
-rw-r--r--libpixelflinger/scanline.cpp24
-rw-r--r--libpixelflinger/tests/arch-mips/Android.mk6
-rw-r--r--libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk18
-rw-r--r--libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c125
-rw-r--r--libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk18
-rw-r--r--libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c134
-rw-r--r--libpixelflinger/tests/arch-mips64/Android.mk3
-rw-r--r--libpixelflinger/tests/arch-mips64/assembler/Android.mk21
-rw-r--r--libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S93
-rw-r--r--libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp644
-rw-r--r--libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk18
-rw-r--r--libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c125
-rw-r--r--libpixelflinger/tests/arch-mips64/disassembler/Android.mk16
-rw-r--r--libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp218
-rw-r--r--libpixelflinger/tests/codegen/codegen.cpp10
32 files changed, 5035 insertions, 279 deletions
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 11e7988b3..87f5a34c3 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -52,6 +52,14 @@ PIXELFLINGER_SRC_FILES_mips := \
52 arch-mips/t32cb16blend.S \ 52 arch-mips/t32cb16blend.S \
53 53
54endif 54endif
55
56PIXELFLINGER_SRC_FILES_mips64 := \
57 codeflinger/MIPSAssembler.cpp \
58 codeflinger/MIPS64Assembler.cpp \
59 codeflinger/mips64_disassem.c \
60 arch-mips64/col32cb16blend.S \
61 arch-mips64/t32cb16blend.S \
62
55# 63#
56# Shared library 64# Shared library
57# 65#
@@ -61,6 +69,7 @@ LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
61LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) 69LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
62LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) 70LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
63LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) 71LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
72LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64)
64LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) 73LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
65LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include 74LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
66LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) 75LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
diff --git a/libpixelflinger/arch-mips/col32cb16blend.S b/libpixelflinger/arch-mips/col32cb16blend.S
new file mode 100644
index 000000000..5d18e5533
--- /dev/null
+++ b/libpixelflinger/arch-mips/col32cb16blend.S
@@ -0,0 +1,134 @@
1/*
2** Copyright 2015, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17 .macro pixel dreg src f sR sG sB shift
18
19#if __mips==32 && __mips_isa_rev>=2
20 /* extract red */
21 ext $t4,\src,\shift+11,5
22 mul $t4,$t4,\f
23
24 /* extract green */
25 ext $t5,\src,\shift+5,6
26 mul $t5,$t5,\f
27
28 /* extract blue */
29 ext $t6,\src,\shift,5
30 mul $t6,$t6,\f
31#else
32 /* extract red */
33 srl $t4,\src,\shift+11
34 andi $t4, 0x1f
35 mul $t4,$t4,\f
36
37 /* extract green */
38 srl $t5,\src,\shift+5
39 andi $t5, 0x3f
40 mul $t5,$t5,\f
41
42 /* extract blue */
43 srl $t6,\src,\shift
44 andi $t6, 0x1f
45 mul $t6,$t6,\f
46#endif
47
48 srl $t4,$t4,8
49 srl $t5,$t5,8
50 srl $t6,$t6,8
51 addu $t4,$t4,\sR
52 addu $t5,$t5,\sG
53 addu \dreg,$t6,\sB
54 sll $t4,$t4,11
55 sll $t5,$t5,5
56 or \dreg,\dreg,$t4
57 or \dreg,\dreg,$t5
58 andi \dreg, 0xffff
59 .endm
60
61 .text
62 .align
63
64 .global scanline_col32cb16blend_mips
65 .ent scanline_col32cb16blend_mips
66scanline_col32cb16blend_mips:
67
68 /* check if count is zero */
69 srl $v0,$a1,24 /* sA */
70 beqz $a2,done
71 li $t4, 0x100
72 srl $v1,$v0,7
73 addu $v0,$v1,$v0
74 subu $v0,$t4,$v0 /* f */
75#if __mips==32 && __mips_isa_rev>=2
76 ext $a3,$a1,3,5 /* sR */
77 ext $t0,$a1,10,6 /* sG */
78 ext $t1,$a1,19,5 /* sB */
79#else
80 srl $a3, $a1, 3
81 andi $a3, 0x1f /* sR */
82 srl $t0, $a1, 10
83 andi $t0, 0x3f /* sG */
84 srl $t1, $a1, 19
85 andi $t1, 0x1f /* sB */
86#endif
87
88 /* check if cnt is at least 4 */
89 addiu $a2,$a2,-4
90 bltz $a2,tail
91
92loop_4pixels:
93 lw $t7,0($a0)
94 lw $t8,4($a0)
95 addiu $a0,$a0,8
96 addiu $a2,$a2,-4
97 pixel $t2 $t7 $v0 $a3 $t0 $t1 0
98 pixel $t3 $t7 $v0 $a3 $t0 $t1 16
99#if __mips==32 && __mips_isa_rev>=2
100 ins $t2,$t3,16,16
101#else
102 sll $t3, 16
103 or $t2, $t2, $t3
104#endif
105 pixel $t7 $t8 $v0 $a3 $t0 $t1 0
106 pixel $t3 $t8 $v0 $a3 $t0 $t1 16
107#if __mips==32 && __mips_isa_rev>=2
108 ins $t7,$t3,16,16
109#else
110 sll $t3, 16
111 or $t7, $t7, $t3
112#endif
113 sw $t2,-8($a0)
114 sw $t7,-4($a0)
115 bgez $a2, loop_4pixels
116
117tail:
118 /* the pixel count underran, restore it now */
119 addiu $a2,$a2,4
120
121 /* handle the last 0..3 pixels */
122 beqz $a2,done
123
124loop_1pixel:
125 lhu $t7,0($a0)
126 addiu $a0,$a0,2
127 addiu $a2,$a2,-1
128 pixel $t2 $t7 $v0 $a3 $t0 $t1 0
129 sh $t2, -2($a0)
130 bnez $a2,loop_1pixel
131
132done:
133 j $ra
134 .end scanline_col32cb16blend_mips
diff --git a/libpixelflinger/arch-mips/t32cb16blend.S b/libpixelflinger/arch-mips/t32cb16blend.S
index c911fbba2..236a2c96e 100644
--- a/libpixelflinger/arch-mips/t32cb16blend.S
+++ b/libpixelflinger/arch-mips/t32cb16blend.S
@@ -33,232 +33,241 @@
33 */ 33 */
34 34
35#if __mips==32 && __mips_isa_rev>=2 35#if __mips==32 && __mips_isa_rev>=2
36 .macro pixel dreg src fb shift 36 .macro pixel dreg src fb shift
37 /* 37 /*
38 * sA = s >> 24 38 * sA = s >> 24
39 * f = 0x100 - (sA + (sA>>7)) 39 * f = 0x100 - (sA + (sA>>7))
40 */ 40 */
41DBG .set noat 41DBG .set noat
42DBG rdhwr $at,$2 42DBG rdhwr $at,$2
43DBG .set at 43DBG .set at
44 44
45 srl $t7,\src,24 45 srl $t7,\src,24
46 srl $t6,$t7,7 46 srl $t6,$t7,7
47 addu $t7,$t6 47 addu $t7,$t6
48 li $t6,0x100 48 li $t6,0x100
49 subu $t7,$t6,$t7 49 subu $t7,$t6,$t7
50 50
51 /* red */ 51 /* red */
52 ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11] 52 ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
53 mul $t6,$t8,$t7 53 mul $t6,$t8,$t7
54 ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5] 54 ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
55 ext $t8,\src,3,5 # src[7..3] 55 ext $t8,\src,3,5 # src[7..3]
56 srl $t6,8 56 srl $t6,8
57 addu $t8,$t6 57 addu $t8,$t6
58 ins \fb,$t8,\shift+6+5,5 # dst[\shift:15..11] 58.if \shift!=0
59 sll $t8,\shift+11
60 or \fb,$t8
61.else
62 sll \fb,$t8,11
63.endif
59 64
60 /* green */ 65 /* green */
61 mul $t8,$t0,$t7 66 mul $t8,$t0,$t7
62 ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0] 67 ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
63 ext $t6,\src,2+8,6 # src[15..10] 68 ext $t6,\src,2+8,6 # src[15..10]
64 srl $t8,8 69 srl $t8,8
65 addu $t8,$t6 70 addu $t8,$t6
66 71
67 /* blue */ 72 /* blue */
68 mul $t0,$t0,$t7 73 mul $t0,$t0,$t7
69 ins \fb,$t8,\shift+5,6 # finish green insertion dst[\shift:10..5] 74 sll $t8, $t8, \shift+5
70 ext $t6,\src,(3+8+8),5 75 or \fb, \fb, $t8
71 srl $t8,$t0,8 76 ext $t6,\src,(3+8+8),5
72 addu $t8,$t6 77 srl $t8,$t0,8
73 ins \fb,$t8,\shift,5 78 addu $t8,$t6
79 sll $t8, $t8, \shift
80 or \fb, \fb, $t8
74 81
75DBG .set noat 82DBG .set noat
76DBG rdhwr $t8,$2 83DBG rdhwr $t8,$2
77DBG subu $t8,$at 84DBG subu $t8,$at
78DBG sltu $at,$t8,$v0 85DBG sltu $at,$t8,$v0
79DBG movn $v0,$t8,$at 86DBG movn $v0,$t8,$at
80DBG sgtu $at,$t8,$v1 87DBG sgtu $at,$t8,$v1
81DBG movn $v1,$t8,$at 88DBG movn $v1,$t8,$at
82DBG .set at 89DBG .set at
83 .endm 90 .endm
84 91
85#else 92#else
86 93
87 .macro pixel dreg src fb shift 94 .macro pixel dreg src fb shift
88 /* 95 /*
89 * sA = s >> 24 96 * sA = s >> 24
90 * f = 0x100 - (sA + (sA>>7)) 97 * f = 0x100 - (sA + (sA>>7))
91 */ 98 */
92DBG .set push 99DBG .set push
93DBG .set noat 100DBG .set noat
94DBG .set mips32r2 101DBG .set mips32r2
95DBG rdhwr $at,$2 102DBG rdhwr $at,$2
96DBG .set pop 103DBG .set pop
97 104
98 srl $t7,\src,24 105 srl $t7,\src,24
99 srl $t6,$t7,7 106 srl $t6,$t7,7
100 addu $t7,$t6 107 addu $t7,$t6
101 li $t6,0x100 108 li $t6,0x100
102 subu $t7,$t6,$t7 109 subu $t7,$t6,$t7
103 110
104 /* 111 /*
105 * red 112 * red
106 * dR = (d >> (6 + 5)) & 0x1f; 113 * dR = (d >> (6 + 5)) & 0x1f;
107 * dR = (f*dR)>>8 114 * dR = (f*dR)>>8
108 * sR = (s >> ( 3)) & 0x1f; 115 * sR = (s >> ( 3)) & 0x1f;
109 * sR += dR 116 * sR += dR
110 * fb |= sR << 11 117 * fb |= sR << 11
111 */ 118 */
112 srl $t8,\dreg,\shift+6+5 119 srl $t8,\dreg,\shift+6+5
113.if \shift==0 120.if \shift==0
114 and $t8,0x1f 121 and $t8,0x1f
115.endif 122.endif
116 mul $t8,$t8,$t7 123 mul $t8,$t8,$t7
117 srl $t6,\src,3 124 srl $t6,\src,3
118 and $t6,0x1f 125 and $t6,0x1f
119 srl $t8,8 126 srl $t8,8
120 addu $t8,$t6 127 addu $t8,$t6
121.if \shift!=0 128.if \shift!=0
122 sll $t8,\shift+11 129 sll $t8,\shift+11
123 or \fb,$t8 130 or \fb,$t8
124.else 131.else
125 sll \fb,$t8,11 132 sll \fb,$t8,11
126.endif 133.endif
127 134
128 /* 135 /*
129 * green 136 * green
130 * dG = (d >> 5) & 0x3f 137 * dG = (d >> 5) & 0x3f
131 * dG = (f*dG) >> 8 138 * dG = (f*dG) >> 8
132 * sG = (s >> ( 8+2))&0x3F; 139 * sG = (s >> ( 8+2))&0x3F;
133 */ 140 */
134 srl $t8,\dreg,\shift+5 141 srl $t8,\dreg,\shift+5
135 and $t8,0x3f 142 and $t8,0x3f
136 mul $t8,$t8,$t7 143 mul $t8,$t8,$t7
137 srl $t6,\src,8+2 144 srl $t6,\src,8+2
138 and $t6,0x3f 145 and $t6,0x3f
139 srl $t8,8 146 srl $t8,8
140 addu $t8,$t6 147 addu $t8,$t6
141 sll $t8,\shift + 5 148 sll $t8,\shift + 5
142 or \fb,$t8 149 or \fb,$t8
143 150
144 /* blue */ 151 /* blue */
145.if \shift!=0 152.if \shift!=0
146 srl $t8,\dreg,\shift 153 srl $t8,\dreg,\shift
147 and $t8,0x1f 154 and $t8,0x1f
148.else 155.else
149 and $t8,\dreg,0x1f 156 and $t8,\dreg,0x1f
150.endif 157.endif
151 mul $t8,$t8,$t7 158 mul $t8,$t8,$t7
152 srl $t6,\src,(8+8+3) 159 srl $t6,\src,(8+8+3)
153 and $t6,0x1f 160 and $t6,0x1f
154 srl $t8,8 161 srl $t8,8
155 addu $t8,$t6 162 addu $t8,$t6
156.if \shift!=0 163.if \shift!=0
157 sll $t8,\shift 164 sll $t8,\shift
158.endif 165.endif
159 or \fb,$t8 166 or \fb,$t8
160DBG .set push 167DBG .set push
161DBG .set noat 168DBG .set noat
162DBG .set mips32r2 169DBG .set mips32r2
163DBG rdhwr $t8,$2 170DBG rdhwr $t8,$2
164DBG subu $t8,$at 171DBG subu $t8,$at
165DBG sltu $at,$t8,$v0 172DBG sltu $at,$t8,$v0
166DBG movn $v0,$t8,$at 173DBG movn $v0,$t8,$at
167DBG sgtu $at,$t8,$v1 174DBG sgtu $at,$t8,$v1
168DBG movn $v1,$t8,$at 175DBG movn $v1,$t8,$at
169DBG .set pop 176DBG .set pop
170 .endm 177 .endm
171#endif 178#endif
172 179
173 .text 180 .text
174 .align 181 .align
175 182
176 .global scanline_t32cb16blend_mips 183 .global scanline_t32cb16blend_mips
177 .ent scanline_t32cb16blend_mips 184 .ent scanline_t32cb16blend_mips
178scanline_t32cb16blend_mips: 185scanline_t32cb16blend_mips:
179DBG li $v0,0xffffffff 186DBG li $v0,0xffffffff
180DBG li $v1,0 187DBG li $v1,0
181 /* Align the destination if necessary */ 188 /* Align the destination if necessary */
182 and $t0,$a0,3 189 and $t0,$a0,3
183 beqz $t0,aligned 190 beqz $t0,aligned
184 191
185 /* as long as there is at least one pixel */ 192 /* as long as there is at least one pixel */
186 beqz $a2,done 193 beqz $a2,done
187 194
188 lw $t4,($a1) 195 lw $t4,($a1)
189 addu $a0,2 196 addu $a0,2
190 addu $a1,4 197 addu $a1,4
191 beqz $t4,1f 198 beqz $t4,1f
192 lhu $t3,-2($a0) 199 lhu $t3,-2($a0)
193 pixel $t3,$t4,$t1,0 200 pixel $t3,$t4,$t1,0
194 sh $t1,-2($a0) 201 sh $t1,-2($a0)
1951: subu $a2,1 2021: subu $a2,1
196 203
197aligned: 204aligned:
198 /* Check to see if its worth unrolling the loop */ 205 /* Check to see if its worth unrolling the loop */
199 subu $a2,4 206 subu $a2,4
200 bltz $a2,tail 207 bltz $a2,tail
201 208
202 /* Process 4 pixels at a time */ 209 /* Process 4 pixels at a time */
203fourpixels: 210fourpixels:
204 /* 1st pair of pixels */ 211 /* 1st pair of pixels */
205 lw $t4,0($a1) 212 lw $t4,0($a1)
206 lw $t5,4($a1) 213 lw $t5,4($a1)
207 addu $a0,8 214 addu $a0,8
208 addu $a1,16 215 addu $a1,16
209 216
210 /* both are zero, skip this pair */ 217 /* both are zero, skip this pair */
211 or $t3,$t4,$t5 218 or $t3,$t4,$t5
212 beqz $t3,1f 219 beqz $t3,1f
213 220
214 /* load the destination */ 221 /* load the destination */
215 lw $t3,-8($a0) 222 lw $t3,-8($a0)
216 223
217 pixel $t3,$t4,$t1,0 224 pixel $t3,$t4,$t1,0
218 pixel $t3,$t5,$t1,16 225 andi $t1, 0xFFFF
219 sw $t1,-8($a0) 226 pixel $t3,$t5,$t1,16
227 sw $t1,-8($a0)
220 228
2211: 2291:
222 /* 2nd pair of pixels */ 230 /* 2nd pair of pixels */
223 lw $t4,-8($a1) 231 lw $t4,-8($a1)
224 lw $t5,-4($a1) 232 lw $t5,-4($a1)
225 233
226 /* both are zero, skip this pair */ 234 /* both are zero, skip this pair */
227 or $t3,$t4,$t5 235 or $t3,$t4,$t5
228 beqz $t3,1f 236 beqz $t3,1f
229 237
230 /* load the destination */ 238 /* load the destination */
231 lw $t3,-4($a0) 239 lw $t3,-4($a0)
232 240
233 pixel $t3,$t4,$t1,0 241 pixel $t3,$t4,$t1,0
234 pixel $t3,$t5,$t1,16 242 andi $t1, 0xFFFF
235 sw $t1,-4($a0) 243 pixel $t3,$t5,$t1,16
244 sw $t1,-4($a0)
236 245
2371: subu $a2,4 2461: subu $a2,4
238 bgtz $a2,fourpixels 247 bgtz $a2,fourpixels
239 248
240tail: 249tail:
241 /* the pixel count underran, restore it now */ 250 /* the pixel count underran, restore it now */
242 addu $a2,4 251 addu $a2,4
243 252
244 /* handle the last 0..3 pixels */ 253 /* handle the last 0..3 pixels */
245 beqz $a2,done 254 beqz $a2,done
246onepixel: 255onepixel:
247 lw $t4,($a1) 256 lw $t4,($a1)
248 addu $a0,2 257 addu $a0,2
249 addu $a1,4 258 addu $a1,4
250 beqz $t4,1f 259 beqz $t4,1f
251 lhu $t3,-2($a0) 260 lhu $t3,-2($a0)
252 pixel $t3,$t4,$t1,0 261 pixel $t3,$t4,$t1,0
253 sh $t1,-2($a0) 262 sh $t1,-2($a0)
2541: subu $a2,1 2631: subu $a2,1
255 bnez $a2,onepixel 264 bnez $a2,onepixel
256done: 265done:
257DBG .set push 266DBG .set push
258DBG .set mips32r2 267DBG .set mips32r2
259DBG rdhwr $a0,$3 268DBG rdhwr $a0,$3
260DBG mul $v0,$a0 269DBG mul $v0,$a0
261DBG mul $v1,$a0 270DBG mul $v1,$a0
262DBG .set pop 271DBG .set pop
263 j $ra 272 j $ra
264 .end scanline_t32cb16blend_mips 273 .end scanline_t32cb16blend_mips
diff --git a/libpixelflinger/arch-mips64/col32cb16blend.S b/libpixelflinger/arch-mips64/col32cb16blend.S
new file mode 100644
index 000000000..fea44911d
--- /dev/null
+++ b/libpixelflinger/arch-mips64/col32cb16blend.S
@@ -0,0 +1,108 @@
1/*
2** Copyright 2015, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17 .macro pixel dreg src f sR sG sB shift
18
19 /* extract red */
20.if \shift < 32
21 dext $t0,\src,\shift+11,5
22.else
23 dextu $t0,\src,\shift+11,5
24.endif
25 mul $t0,$t0,\f
26
27 /* extract green */
28.if \shift < 32
29 dext $t1,\src,\shift+5,6
30.else
31 dextu $t1,\src,\shift+5,6
32.endif
33 mul $t1,$t1,\f
34
35 /* extract blue */
36.if \shift < 32
37 dext $t2,\src,\shift,5
38.else
39 dextu $t2,\src,\shift,5
40.endif
41 mul $t2,$t2,\f
42
43 srl $t0,$t0,8
44 srl $t1,$t1,8
45 srl $t2,$t2,8
46 addu $t0,$t0,\sR
47 addu $t1,$t1,\sG
48 addu \dreg,$t2,\sB
49 sll $t0,$t0,11
50 sll $t1,$t1,5
51 or \dreg,\dreg,$t0
52 or \dreg,\dreg,$t1
53 .endm
54
55 .text
56 .align
57
58 .global scanline_col32cb16blend_mips64
59 .ent scanline_col32cb16blend_mips64
60scanline_col32cb16blend_mips64:
61
62 /* check if count is zero */
63 srl $v0,$a1,24 /* sA */
64 beqz $a2,done
65 li $t0, 0x100
66 srl $v1,$v0,7
67 addu $v0,$v1,$v0
68 subu $v0,$t0,$v0 /* f */
69 ext $a3,$a1,3,5 /* sR */
70 ext $a4,$a1,10,6 /* sG */
71 ext $a5,$a1,19,5 /* sB */
72
73 /* check if cnt is at least 4 */
74 addiu $a2,$a2,-4
75 bltz $a2,tail
76
77loop_4pixels:
78 ld $t3,0($a0)
79 daddiu $a0,$a0,8
80 addiu $a2,$a2,-4
81 pixel $a6 $t3 $v0 $a3 $a4 $a5 0
82 pixel $a7 $t3 $v0 $a3 $a4 $a5 16
83 pixel $t8 $t3 $v0 $a3 $a4 $a5 32
84 pixel $t9 $t3 $v0 $a3 $a4 $a5 48
85 dins $a6,$a7,16,16
86 dinsu $a6,$t8,32,16
87 dinsu $a6,$t9,48,16
88 sd $a6,-8($a0)
89 bgez $a2, loop_4pixels
90
91tail:
92 /* the pixel count underran, restore it now */
93 addiu $a2,$a2,4
94
95 /* handle the last 0..3 pixels */
96 beqz $a2,done
97
98loop_1pixel:
99 lhu $t3,0($a0)
100 daddiu $a0,$a0,2
101 addiu $a2,$a2,-1
102 pixel $a6 $t3 $v0 $a3 $a4 $a5 0
103 sh $a6, -2($a0)
104 bnez $a2,loop_1pixel
105
106done:
107 j $ra
108 .end scanline_col32cb16blend_mips64
diff --git a/libpixelflinger/arch-mips64/t32cb16blend.S b/libpixelflinger/arch-mips64/t32cb16blend.S
new file mode 100644
index 000000000..d2f4d4905
--- /dev/null
+++ b/libpixelflinger/arch-mips64/t32cb16blend.S
@@ -0,0 +1,172 @@
1/*
2** Copyright 2015, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17#ifdef DEBUG
18#define DBG
19#else
20#define DBG #
21#endif
22
23/*
24 * blend one of 2 16bpp RGB pixels held in dreg selected by shift
25 * with the 32bpp ABGR pixel held in src and store the result in fb
26 *
27 * Assumes that the dreg data is little endian and that
28 * the the second pixel (shift==16) will be merged into
29 * the fb result
30 *
31 * Uses $a4,$t2,$t3,$t8
32 */
33
34 .macro pixel dreg src fb shift
35 /*
36 * sA = s >> 24
37 * f = 0x100 - (sA + (sA>>7))
38 */
39 srl $t3,\src,24
40 srl $t2,$t3,7
41 addu $t3,$t2
42 li $t2,0x100
43 subu $t3,$t2,$t3
44
45 /* red */
46 ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11]
47 mul $t2,$t8,$t3
48 ext $a4,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5]
49 ext $t8,\src,3,5 # src[7..3]
50 srl $t2,8
51 addu $t8,$t2
52.if \shift!=0
53 sll $t8,\shift+11 # dst[\shift:15..11]
54 or \fb,$t8
55.else
56 sll \fb,$t8,11
57.endif
58
59 /* green */
60 mul $t8,$a4,$t3
61 ext $a4,\dreg,\shift,5 # start blue extraction dst[\shift:4..0]
62 ext $t2,\src,2+8,6 # src[15..10]
63 srl $t8,8
64 addu $t8,$t2
65
66 /* blue */
67 mul $a4,$a4,$t3
68 sll $t8, $t8, \shift+5 # finish green insertion dst[\shift:10..5]
69 or \fb, \fb, $t8
70 ext $t2,\src,(3+8+8),5
71 srl $t8,$a4,8
72 addu $t8,$t2
73 sll $t8, $t8, \shift
74 or \fb, \fb, $t8
75 .endm
76
77 .text
78 .align
79
80 .global scanline_t32cb16blend_mips64
81 .ent scanline_t32cb16blend_mips64
82scanline_t32cb16blend_mips64:
83 daddiu $sp, $sp, -40
84DBG li $v0,0xffffffff
85DBG li $v1,0
86 /* Align the destination if necessary */
87 and $a4,$a0,3
88 beqz $a4,aligned
89
90 /* as long as there is at least one pixel */
91 beqz $a2,done
92
93 lw $t0,($a1)
94 daddu $a0,2
95 daddu $a1,4
96 beqz $t0,1f
97 lhu $a7,-2($a0)
98 pixel $a7,$t0,$a5,0
99 sh $a5,-2($a0)
1001: subu $a2,1
101
102aligned:
103 /* Check to see if its worth unrolling the loop */
104 subu $a2,4
105 bltz $a2,tail
106
107 /* Process 4 pixels at a time */
108fourpixels:
109 /* 1st pair of pixels */
110 lw $t0,0($a1)
111 lw $t1,4($a1)
112 daddu $a0,8
113 daddu $a1,16
114
115 /* both are zero, skip this pair */
116 or $a7,$t0,$t1
117 beqz $a7,1f
118
119 /* load the destination */
120 lw $a7,-8($a0)
121
122 pixel $a7,$t0,$a5,0
123 andi $a5, 0xFFFF
124 pixel $a7,$t1,$a5,16
125 sw $a5,-8($a0)
126
1271:
128 /* 2nd pair of pixels */
129 lw $t0,-8($a1)
130 lw $t1,-4($a1)
131
132 /* both are zero, skip this pair */
133 or $a7,$t0,$t1
134 beqz $a7,1f
135
136 /* load the destination */
137 lw $a7,-4($a0)
138
139 pixel $a7,$t0,$a5,0
140 andi $a5, 0xFFFF
141 pixel $a7,$t1,$a5,16
142 sw $a5,-4($a0)
143
1441: subu $a2,4
145 bgtz $a2,fourpixels
146
147tail:
148 /* the pixel count underran, restore it now */
149 addu $a2,4
150
151 /* handle the last 0..3 pixels */
152 beqz $a2,done
153onepixel:
154 lw $t0,($a1)
155 daddu $a0,2
156 daddu $a1,4
157 beqz $t0,1f
158 lhu $a7,-2($a0)
159 pixel $a7,$t0,$a5,0
160 sh $a5,-2($a0)
1611: subu $a2,1
162 bnez $a2,onepixel
163done:
164DBG .set push
165DBG .set mips32r2
166DBG rdhwr $a0,$3
167DBG mul $v0,$a0
168DBG mul $v1,$a0
169DBG .set pop
170 daddiu $sp, $sp, 40
171 j $ra
172 .end scanline_t32cb16blend_mips64
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.h b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
index 40cbfcfb9..72935acd2 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
@@ -63,7 +63,7 @@ public:
63 }; 63 };
64 64
65 enum { 65 enum {
66 CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64 66 CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS, CODEGEN_ARCH_ARM64, CODEGEN_ARCH_MIPS64
67 }; 67 };
68 68
69 // ----------------------------------------------------------------------- 69 // -----------------------------------------------------------------------
@@ -115,7 +115,8 @@ public:
115 // data processing... 115 // data processing...
116 enum { 116 enum {
117 opAND, opEOR, opSUB, opRSB, opADD, opADC, opSBC, opRSC, 117 opAND, opEOR, opSUB, opRSB, opADD, opADC, opSBC, opRSC,
118 opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN 118 opTST, opTEQ, opCMP, opCMN, opORR, opMOV, opBIC, opMVN,
119 opADD64, opSUB64
119 }; 120 };
120 121
121 virtual void 122 virtual void
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 325caba8a..346779f47 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -893,7 +893,8 @@ void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits)
893 return; 893 return;
894 } 894 }
895 895
896 if (getCodegenArch() == CODEGEN_ARCH_MIPS) { 896 if ((getCodegenArch() == CODEGEN_ARCH_MIPS) ||
897 (getCodegenArch() == CODEGEN_ARCH_MIPS64)) {
897 // MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr 898 // MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr
898 // the below ' while (mask)' code is buggy on mips 899 // the below ' while (mask)' code is buggy on mips
899 // since mips returns true on isValidImmediate() 900 // since mips returns true on isValidImmediate()
@@ -1057,7 +1058,8 @@ RegisterAllocator::RegisterFile& RegisterAllocator::registerFile()
1057RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch) 1058RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
1058 : mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0) 1059 : mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0)
1059{ 1060{
1060 if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) { 1061 if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) ||
1062 (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) {
1061 mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17 1063 mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
1062 } 1064 }
1063 reserve(ARMAssemblerInterface::SP); 1065 reserve(ARMAssemblerInterface::SP);
@@ -1067,7 +1069,8 @@ RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
1067RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch) 1069RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch)
1068 : mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0) 1070 : mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0)
1069{ 1071{
1070 if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) { 1072 if ((mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) ||
1073 (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS64)) {
1071 mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17 1074 mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
1072 } 1075 }
1073} 1076}
diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.cpp b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
new file mode 100644
index 000000000..a5305cca2
--- /dev/null
+++ b/libpixelflinger/codeflinger/MIPS64Assembler.cpp
@@ -0,0 +1,1452 @@
1/* libs/pixelflinger/codeflinger/MIPS64Assembler.cpp
2**
3** Copyright 2015, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19/* MIPS64 assembler and ARM->MIPS64 assembly translator
20**
21** The approach is utilize MIPSAssembler generator, using inherited MIPS64Assembler
22** that overrides just the specific MIPS64r6 instructions.
23** For now ArmToMips64Assembler is copied over from ArmToMipsAssembler class,
24** changing some MIPS64r6 related stuff.
25**
26*/
27
28
29#define LOG_TAG "MIPS64Assembler"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <cutils/log.h>
34#include <cutils/properties.h>
35
36#if defined(WITH_LIB_HARDWARE)
37#include <hardware_legacy/qemu_tracing.h>
38#endif
39
40#include <private/pixelflinger/ggl_context.h>
41
42#include "MIPS64Assembler.h"
43#include "CodeCache.h"
44#include "mips64_disassem.h"
45
46
47#define NOT_IMPLEMENTED() LOG_ALWAYS_FATAL("Arm instruction %s not yet implemented\n", __func__)
48
49
50// ----------------------------------------------------------------------------
51
52namespace android {
53
54// ----------------------------------------------------------------------------
55#if 0
56#pragma mark -
57#pragma mark ArmToMips64Assembler...
58#endif
59
60ArmToMips64Assembler::ArmToMips64Assembler(const sp<Assembly>& assembly,
61 char *abuf, int linesz, int instr_count)
62 : ARMAssemblerInterface(),
63 mArmDisassemblyBuffer(abuf),
64 mArmLineLength(linesz),
65 mArmInstrCount(instr_count),
66 mInum(0),
67 mAssembly(assembly)
68{
69 mMips = new MIPS64Assembler(assembly, this);
70 mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
71 init_conditional_labels();
72}
73
74ArmToMips64Assembler::ArmToMips64Assembler(void* assembly)
75 : ARMAssemblerInterface(),
76 mArmDisassemblyBuffer(NULL),
77 mInum(0),
78 mAssembly(NULL)
79{
80 mMips = new MIPS64Assembler(assembly, this);
81 mArmPC = (uint32_t **) malloc(ARM_MAX_INSTUCTIONS * sizeof(uint32_t *));
82 init_conditional_labels();
83}
84
85ArmToMips64Assembler::~ArmToMips64Assembler()
86{
87 delete mMips;
88 free((void *) mArmPC);
89}
90
91uint32_t* ArmToMips64Assembler::pc() const
92{
93 return mMips->pc();
94}
95
96uint32_t* ArmToMips64Assembler::base() const
97{
98 return mMips->base();
99}
100
101void ArmToMips64Assembler::reset()
102{
103 cond.labelnum = 0;
104 mInum = 0;
105 mMips->reset();
106}
107
108int ArmToMips64Assembler::getCodegenArch()
109{
110 return CODEGEN_ARCH_MIPS64;
111}
112
113void ArmToMips64Assembler::comment(const char* string)
114{
115 mMips->comment(string);
116}
117
118void ArmToMips64Assembler::label(const char* theLabel)
119{
120 mMips->label(theLabel);
121}
122
123void ArmToMips64Assembler::disassemble(const char* name)
124{
125 mMips->disassemble(name);
126}
127
128void ArmToMips64Assembler::init_conditional_labels()
129{
130 int i;
131 for (i=0;i<99; ++i) {
132 sprintf(cond.label[i], "cond_%d", i);
133 }
134}
135
136
137
138#if 0
139#pragma mark -
140#pragma mark Prolog/Epilog & Generate...
141#endif
142
143void ArmToMips64Assembler::prolog()
144{
145 mArmPC[mInum++] = pc(); // save starting PC for this instr
146
147 mMips->DADDIU(R_sp, R_sp, -(5 * 8));
148 mMips->SD(R_s0, R_sp, 0);
149 mMips->SD(R_s1, R_sp, 8);
150 mMips->SD(R_s2, R_sp, 16);
151 mMips->SD(R_s3, R_sp, 24);
152 mMips->SD(R_s4, R_sp, 32);
153 mMips->MOVE(R_v0, R_a0); // move context * passed in a0 to v0 (arm r0)
154}
155
156void ArmToMips64Assembler::epilog(uint32_t touched)
157{
158 mArmPC[mInum++] = pc(); // save starting PC for this instr
159
160 mMips->LD(R_s0, R_sp, 0);
161 mMips->LD(R_s1, R_sp, 8);
162 mMips->LD(R_s2, R_sp, 16);
163 mMips->LD(R_s3, R_sp, 24);
164 mMips->LD(R_s4, R_sp, 32);
165 mMips->DADDIU(R_sp, R_sp, (5 * 8));
166 mMips->JR(R_ra);
167
168}
169
170int ArmToMips64Assembler::generate(const char* name)
171{
172 return mMips->generate(name);
173}
174
175void ArmToMips64Assembler::fix_branches()
176{
177 mMips->fix_branches();
178}
179
180uint32_t* ArmToMips64Assembler::pcForLabel(const char* label)
181{
182 return mMips->pcForLabel(label);
183}
184
185void ArmToMips64Assembler::set_condition(int mode, int R1, int R2) {
186 if (mode == 2) {
187 cond.type = SBIT_COND;
188 } else {
189 cond.type = CMP_COND;
190 }
191 cond.r1 = R1;
192 cond.r2 = R2;
193}
194
195//----------------------------------------------------------
196
197#if 0
198#pragma mark -
199#pragma mark Addressing modes & shifters...
200#endif
201
202
203// do not need this for MIPS, but it is in the Interface (virtual)
204int ArmToMips64Assembler::buildImmediate(
205 uint32_t immediate, uint32_t& rot, uint32_t& imm)
206{
207 // for MIPS, any 32-bit immediate is OK
208 rot = 0;
209 imm = immediate;
210 return 0;
211}
212
213// shifters...
214
215bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate)
216{
217 // for MIPS, any 32-bit immediate is OK
218 return true;
219}
220
221uint32_t ArmToMips64Assembler::imm(uint32_t immediate)
222{
223 amode.value = immediate;
224 return AMODE_IMM;
225}
226
227uint32_t ArmToMips64Assembler::reg_imm(int Rm, int type, uint32_t shift)
228{
229 amode.reg = Rm;
230 amode.stype = type;
231 amode.value = shift;
232 return AMODE_REG_IMM;
233}
234
235uint32_t ArmToMips64Assembler::reg_rrx(int Rm)
236{
237 // reg_rrx mode is not used in the GLLAssember code at this time
238 return AMODE_UNSUPPORTED;
239}
240
241uint32_t ArmToMips64Assembler::reg_reg(int Rm, int type, int Rs)
242{
243 // reg_reg mode is not used in the GLLAssember code at this time
244 return AMODE_UNSUPPORTED;
245}
246
247
248// addressing modes...
249// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
250uint32_t ArmToMips64Assembler::immed12_pre(int32_t immed12, int W)
251{
252 LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
253 "LDR(B)/STR(B)/PLD immediate too big (%08x)",
254 immed12);
255 amode.value = immed12;
256 amode.writeback = W;
257 return AMODE_IMM_12_PRE;
258}
259
260uint32_t ArmToMips64Assembler::immed12_post(int32_t immed12)
261{
262 LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
263 "LDR(B)/STR(B)/PLD immediate too big (%08x)",
264 immed12);
265
266 amode.value = immed12;
267 return AMODE_IMM_12_POST;
268}
269
270uint32_t ArmToMips64Assembler::reg_scale_pre(int Rm, int type,
271 uint32_t shift, int W)
272{
273 LOG_ALWAYS_FATAL_IF(W | type | shift, "reg_scale_pre adv modes not yet implemented");
274
275 amode.reg = Rm;
276 // amode.stype = type; // more advanced modes not used in GGLAssembler yet
277 // amode.value = shift;
278 // amode.writeback = W;
279 return AMODE_REG_SCALE_PRE;
280}
281
282uint32_t ArmToMips64Assembler::reg_scale_post(int Rm, int type, uint32_t shift)
283{
284 LOG_ALWAYS_FATAL("adr mode reg_scale_post not yet implemented\n");
285 return AMODE_UNSUPPORTED;
286}
287
288// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
289uint32_t ArmToMips64Assembler::immed8_pre(int32_t immed8, int W)
290{
291 LOG_ALWAYS_FATAL("adr mode immed8_pre not yet implemented\n");
292
293 LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
294 "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
295 immed8);
296 return AMODE_IMM_8_PRE;
297}
298
299uint32_t ArmToMips64Assembler::immed8_post(int32_t immed8)
300{
301 LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
302 "LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
303 immed8);
304 amode.value = immed8;
305 return AMODE_IMM_8_POST;
306}
307
308uint32_t ArmToMips64Assembler::reg_pre(int Rm, int W)
309{
310 LOG_ALWAYS_FATAL_IF(W, "reg_pre writeback not yet implemented");
311 amode.reg = Rm;
312 return AMODE_REG_PRE;
313}
314
315uint32_t ArmToMips64Assembler::reg_post(int Rm)
316{
317 LOG_ALWAYS_FATAL("adr mode reg_post not yet implemented\n");
318 return AMODE_UNSUPPORTED;
319}
320
321
322
323// ----------------------------------------------------------------------------
324
325#if 0
326#pragma mark -
327#pragma mark Data Processing...
328#endif
329
330
331static const char * const dpOpNames[] = {
332 "AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC",
333 "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"
334};
335
336// check if the operand registers from a previous CMP or S-bit instruction
337// would be overwritten by this instruction. If so, move the value to a
338// safe register.
339// Note that we cannot tell at _this_ instruction time if a future (conditional)
340// instruction will _also_ use this value (a defect of the simple 1-pass, one-
341// instruction-at-a-time translation). Therefore we must be conservative and
342// save the value before it is overwritten. This costs an extra MOVE instr.
343
344void ArmToMips64Assembler::protectConditionalOperands(int Rd)
345{
346 if (Rd == cond.r1) {
347 mMips->MOVE(R_cmp, cond.r1);
348 cond.r1 = R_cmp;
349 }
350 if (cond.type == CMP_COND && Rd == cond.r2) {
351 mMips->MOVE(R_cmp2, cond.r2);
352 cond.r2 = R_cmp2;
353 }
354}
355
356
357// interprets the addressing mode, and generates the common code
358// used by the majority of data-processing ops. Many MIPS instructions
359// have a register-based form and a different immediate form. See
360// opAND below for an example. (this could be inlined)
361//
362// this works with the imm(), reg_imm() methods above, which are directly
363// called by the GLLAssembler.
364// note: _signed parameter defaults to false (un-signed)
365// note: tmpReg parameter defaults to 1, MIPS register AT
366int ArmToMips64Assembler::dataProcAdrModes(int op, int& source, bool _signed, int tmpReg)
367{
368 if (op < AMODE_REG) {
369 source = op;
370 return SRC_REG;
371 } else if (op == AMODE_IMM) {
372 if ((!_signed && amode.value > 0xffff)
373 || (_signed && ((int)amode.value < -32768 || (int)amode.value > 32767) )) {
374 mMips->LUI(tmpReg, (amode.value >> 16));
375 if (amode.value & 0x0000ffff) {
376 mMips->ORI(tmpReg, tmpReg, (amode.value & 0x0000ffff));
377 }
378 source = tmpReg;
379 return SRC_REG;
380 } else {
381 source = amode.value;
382 return SRC_IMM;
383 }
384 } else if (op == AMODE_REG_IMM) {
385 switch (amode.stype) {
386 case LSL: mMips->SLL(tmpReg, amode.reg, amode.value); break;
387 case LSR: mMips->SRL(tmpReg, amode.reg, amode.value); break;
388 case ASR: mMips->SRA(tmpReg, amode.reg, amode.value); break;
389 case ROR: mMips->ROTR(tmpReg, amode.reg, amode.value); break;
390 }
391 source = tmpReg;
392 return SRC_REG;
393 } else { // adr mode RRX is not used in GGL Assembler at this time
394 // we are screwed, this should be exception, assert-fail or something
395 LOG_ALWAYS_FATAL("adr mode reg_rrx not yet implemented\n");
396 return SRC_ERROR;
397 }
398}
399
400
401void ArmToMips64Assembler::dataProcessing(int opcode, int cc,
402 int s, int Rd, int Rn, uint32_t Op2)
403{
404 int src; // src is modified by dataProcAdrModes() - passed as int&
405
406 if (cc != AL) {
407 protectConditionalOperands(Rd);
408 // the branch tests register(s) set by prev CMP or instr with 'S' bit set
409 // inverse the condition to jump past this conditional instruction
410 ArmToMips64Assembler::B(cc^1, cond.label[++cond.labelnum]);
411 } else {
412 mArmPC[mInum++] = pc(); // save starting PC for this instr
413 }
414
415 switch (opcode) {
416 case opAND:
417 if (dataProcAdrModes(Op2, src) == SRC_REG) {
418 mMips->AND(Rd, Rn, src);
419 } else { // adr mode was SRC_IMM
420 mMips->ANDI(Rd, Rn, src);
421 }
422 break;
423
424 case opADD:
425 // set "signed" to true for adr modes
426 if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
427 mMips->ADDU(Rd, Rn, src);
428 } else { // adr mode was SRC_IMM
429 mMips->ADDIU(Rd, Rn, src);
430 }
431 break;
432
433 case opSUB:
434 // set "signed" to true for adr modes
435 if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
436 mMips->SUBU(Rd, Rn, src);
437 } else { // adr mode was SRC_IMM
438 mMips->SUBIU(Rd, Rn, src);
439 }
440 break;
441
442 case opADD64:
443 // set "signed" to true for adr modes
444 if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
445 mMips->DADDU(Rd, Rn, src);
446 } else { // adr mode was SRC_IMM
447 mMips->DADDIU(Rd, Rn, src);
448 }
449 break;
450
451 case opSUB64:
452 // set "signed" to true for adr modes
453 if (dataProcAdrModes(Op2, src, true) == SRC_REG) {
454 mMips->DSUBU(Rd, Rn, src);
455 } else { // adr mode was SRC_IMM
456 mMips->DSUBIU(Rd, Rn, src);
457 }
458 break;
459
460 case opEOR:
461 if (dataProcAdrModes(Op2, src) == SRC_REG) {
462 mMips->XOR(Rd, Rn, src);
463 } else { // adr mode was SRC_IMM
464 mMips->XORI(Rd, Rn, src);
465 }
466 break;
467
468 case opORR:
469 if (dataProcAdrModes(Op2, src) == SRC_REG) {
470 mMips->OR(Rd, Rn, src);
471 } else { // adr mode was SRC_IMM
472 mMips->ORI(Rd, Rn, src);
473 }
474 break;
475
476 case opBIC:
477 if (dataProcAdrModes(Op2, src) == SRC_IMM) {
478 // if we are 16-bit imnmediate, load to AT reg
479 mMips->ORI(R_at, 0, src);
480 src = R_at;
481 }
482 mMips->NOT(R_at, src);
483 mMips->AND(Rd, Rn, R_at);
484 break;
485
486 case opRSB:
487 if (dataProcAdrModes(Op2, src) == SRC_IMM) {
488 // if we are 16-bit imnmediate, load to AT reg
489 mMips->ORI(R_at, 0, src);
490 src = R_at;
491 }
492 mMips->SUBU(Rd, src, Rn); // subu with the parameters reversed
493 break;
494
495 case opMOV:
496 if (Op2 < AMODE_REG) { // op2 is reg # in this case
497 mMips->MOVE(Rd, Op2);
498 } else if (Op2 == AMODE_IMM) {
499 if (amode.value > 0xffff) {
500 mMips->LUI(Rd, (amode.value >> 16));
501 if (amode.value & 0x0000ffff) {
502 mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
503 }
504 } else {
505 mMips->ORI(Rd, 0, amode.value);
506 }
507 } else if (Op2 == AMODE_REG_IMM) {
508 switch (amode.stype) {
509 case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
510 case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
511 case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
512 case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break;
513 }
514 }
515 else {
516 // adr mode RRX is not used in GGL Assembler at this time
517 mMips->UNIMPL();
518 }
519 break;
520
521 case opMVN: // this is a 1's complement: NOT
522 if (Op2 < AMODE_REG) { // op2 is reg # in this case
523 mMips->NOR(Rd, Op2, 0); // NOT is NOR with 0
524 break;
525 } else if (Op2 == AMODE_IMM) {
526 if (amode.value > 0xffff) {
527 mMips->LUI(Rd, (amode.value >> 16));
528 if (amode.value & 0x0000ffff) {
529 mMips->ORI(Rd, Rd, (amode.value & 0x0000ffff));
530 }
531 } else {
532 mMips->ORI(Rd, 0, amode.value);
533 }
534 } else if (Op2 == AMODE_REG_IMM) {
535 switch (amode.stype) {
536 case LSL: mMips->SLL(Rd, amode.reg, amode.value); break;
537 case LSR: mMips->SRL(Rd, amode.reg, amode.value); break;
538 case ASR: mMips->SRA(Rd, amode.reg, amode.value); break;
539 case ROR: mMips->ROTR(Rd, amode.reg, amode.value); break;
540 }
541 }
542 else {
543 // adr mode RRX is not used in GGL Assembler at this time
544 mMips->UNIMPL();
545 }
546 mMips->NOR(Rd, Rd, 0); // NOT is NOR with 0
547 break;
548
549 case opCMP:
550 // Either operand of a CMP instr could get overwritten by a subsequent
551 // conditional instruction, which is ok, _UNLESS_ there is a _second_
552 // conditional instruction. Under MIPS, this requires doing the comparison
553 // again (SLT), and the original operands must be available. (and this
554 // pattern of multiple conditional instructions from same CMP _is_ used
555 // in GGL-Assembler)
556 //
557 // For now, if a conditional instr overwrites the operands, we will
558 // move them to dedicated temp regs. This is ugly, and inefficient,
559 // and should be optimized.
560 //
561 // WARNING: making an _Assumption_ that CMP operand regs will NOT be
562 // trashed by intervening NON-conditional instructions. In the general
563 // case this is legal, but it is NOT currently done in GGL-Assembler.
564
565 cond.type = CMP_COND;
566 cond.r1 = Rn;
567 if (dataProcAdrModes(Op2, src, false, R_cmp2) == SRC_REG) {
568 cond.r2 = src;
569 } else { // adr mode was SRC_IMM
570 mMips->ORI(R_cmp2, R_zero, src);
571 cond.r2 = R_cmp2;
572 }
573
574 break;
575
576
577 case opTST:
578 case opTEQ:
579 case opCMN:
580 case opADC:
581 case opSBC:
582 case opRSC:
583 mMips->UNIMPL(); // currently unused in GGL Assembler code
584 break;
585 }
586
587 if (cc != AL) {
588 mMips->label(cond.label[cond.labelnum]);
589 }
590 if (s && opcode != opCMP) {
591 cond.type = SBIT_COND;
592 cond.r1 = Rd;
593 }
594}
595
596
597
598#if 0
599#pragma mark -
600#pragma mark Multiply...
601#endif
602
603// multiply, accumulate
604void ArmToMips64Assembler::MLA(int cc, int s,
605 int Rd, int Rm, int Rs, int Rn) {
606
607 //ALOGW("MLA");
608 mArmPC[mInum++] = pc(); // save starting PC for this instr
609
610 mMips->MUL(R_at, Rm, Rs);
611 mMips->ADDU(Rd, R_at, Rn);
612 if (s) {
613 cond.type = SBIT_COND;
614 cond.r1 = Rd;
615 }
616}
617
618void ArmToMips64Assembler::MUL(int cc, int s,
619 int Rd, int Rm, int Rs) {
620 mArmPC[mInum++] = pc();
621 mMips->MUL(Rd, Rm, Rs);
622 if (s) {
623 cond.type = SBIT_COND;
624 cond.r1 = Rd;
625 }
626}
627
628void ArmToMips64Assembler::UMULL(int cc, int s,
629 int RdLo, int RdHi, int Rm, int Rs) {
630 mArmPC[mInum++] = pc();
631 mMips->MUH(RdHi, Rm, Rs);
632 mMips->MUL(RdLo, Rm, Rs);
633
634 if (s) {
635 cond.type = SBIT_COND;
636 cond.r1 = RdHi; // BUG...
637 LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
638 }
639}
640
641void ArmToMips64Assembler::UMUAL(int cc, int s,
642 int RdLo, int RdHi, int Rm, int Rs) {
643 LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
644 "UMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
645 // *mPC++ = (cc<<28) | (1<<23) | (1<<21) | (s<<20) |
646 // (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
647 mArmPC[mInum++] = pc();
648 mMips->NOP2();
649 NOT_IMPLEMENTED();
650 if (s) {
651 cond.type = SBIT_COND;
652 cond.r1 = RdHi; // BUG...
653 LOG_ALWAYS_FATAL("Condition on UMULL must be on 64-bit result\n");
654 }
655}
656
657void ArmToMips64Assembler::SMULL(int cc, int s,
658 int RdLo, int RdHi, int Rm, int Rs) {
659 LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
660 "SMULL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
661 // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (s<<20) |
662 // (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
663 mArmPC[mInum++] = pc();
664 mMips->NOP2();
665 NOT_IMPLEMENTED();
666 if (s) {
667 cond.type = SBIT_COND;
668 cond.r1 = RdHi; // BUG...
669 LOG_ALWAYS_FATAL("Condition on SMULL must be on 64-bit result\n");
670 }
671}
672void ArmToMips64Assembler::SMUAL(int cc, int s,
673 int RdLo, int RdHi, int Rm, int Rs) {
674 LOG_FATAL_IF(RdLo==Rm || RdHi==Rm || RdLo==RdHi,
675 "SMUAL(r%u,r%u,r%u,r%u)", RdLo,RdHi,Rm,Rs);
676 // *mPC++ = (cc<<28) | (1<<23) | (1<<22) | (1<<21) | (s<<20) |
677 // (RdHi<<16) | (RdLo<<12) | (Rs<<8) | 0x90 | Rm;
678 mArmPC[mInum++] = pc();
679 mMips->NOP2();
680 NOT_IMPLEMENTED();
681 if (s) {
682 cond.type = SBIT_COND;
683 cond.r1 = RdHi; // BUG...
684 LOG_ALWAYS_FATAL("Condition on SMUAL must be on 64-bit result\n");
685 }
686}
687
688
689
690#if 0
691#pragma mark -
692#pragma mark Branches...
693#endif
694
695// branches...
696
697void ArmToMips64Assembler::B(int cc, const char* label)
698{
699 mArmPC[mInum++] = pc();
700 if (cond.type == SBIT_COND) { cond.r2 = R_zero; }
701
702 switch(cc) {
703 case EQ: mMips->BEQ(cond.r1, cond.r2, label); break;
704 case NE: mMips->BNE(cond.r1, cond.r2, label); break;
705 case HS: mMips->BGEU(cond.r1, cond.r2, label); break;
706 case LO: mMips->BLTU(cond.r1, cond.r2, label); break;
707 case MI: mMips->BLT(cond.r1, cond.r2, label); break;
708 case PL: mMips->BGE(cond.r1, cond.r2, label); break;
709
710 case HI: mMips->BGTU(cond.r1, cond.r2, label); break;
711 case LS: mMips->BLEU(cond.r1, cond.r2, label); break;
712 case GE: mMips->BGE(cond.r1, cond.r2, label); break;
713 case LT: mMips->BLT(cond.r1, cond.r2, label); break;
714 case GT: mMips->BGT(cond.r1, cond.r2, label); break;
715 case LE: mMips->BLE(cond.r1, cond.r2, label); break;
716 case AL: mMips->B(label); break;
717 case NV: /* B Never - no instruction */ break;
718
719 case VS:
720 case VC:
721 default:
722 LOG_ALWAYS_FATAL("Unsupported cc: %02x\n", cc);
723 break;
724 }
725}
726
727void ArmToMips64Assembler::BL(int cc, const char* label)
728{
729 LOG_ALWAYS_FATAL("branch-and-link not supported yet\n");
730 mArmPC[mInum++] = pc();
731}
732
733// no use for Branches with integer PC, but they're in the Interface class ....
734void ArmToMips64Assembler::B(int cc, uint32_t* to_pc)
735{
736 LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
737 mArmPC[mInum++] = pc();
738}
739
740void ArmToMips64Assembler::BL(int cc, uint32_t* to_pc)
741{
742 LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
743 mArmPC[mInum++] = pc();
744}
745
746void ArmToMips64Assembler::BX(int cc, int Rn)
747{
748 LOG_ALWAYS_FATAL("branch to absolute PC not supported, use Label\n");
749 mArmPC[mInum++] = pc();
750}
751
752
753
754#if 0
755#pragma mark -
756#pragma mark Data Transfer...
757#endif
758
759// data transfer...
760void ArmToMips64Assembler::LDR(int cc, int Rd, int Rn, uint32_t offset)
761{
762 mArmPC[mInum++] = pc();
763 // work-around for ARM default address mode of immed12_pre(0)
764 if (offset > AMODE_UNSUPPORTED) offset = 0;
765 switch (offset) {
766 case 0:
767 amode.value = 0;
768 amode.writeback = 0;
769 // fall thru to next case ....
770 case AMODE_IMM_12_PRE:
771 if (Rn == ARMAssemblerInterface::SP) {
772 Rn = R_sp; // convert LDR via Arm SP to LW via Mips SP
773 }
774 mMips->LW(Rd, Rn, amode.value);
775 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
776 mMips->DADDIU(Rn, Rn, amode.value);
777 }
778 break;
779 case AMODE_IMM_12_POST:
780 if (Rn == ARMAssemblerInterface::SP) {
781 Rn = R_sp; // convert STR thru Arm SP to STR thru Mips SP
782 }
783 mMips->LW(Rd, Rn, 0);
784 mMips->DADDIU(Rn, Rn, amode.value);
785 break;
786 case AMODE_REG_SCALE_PRE:
787 // we only support simple base + index, no advanced modes for this one yet
788 mMips->DADDU(R_at, Rn, amode.reg);
789 mMips->LW(Rd, R_at, 0);
790 break;
791 }
792}
793
794void ArmToMips64Assembler::LDRB(int cc, int Rd, int Rn, uint32_t offset)
795{
796 mArmPC[mInum++] = pc();
797 // work-around for ARM default address mode of immed12_pre(0)
798 if (offset > AMODE_UNSUPPORTED) offset = 0;
799 switch (offset) {
800 case 0:
801 amode.value = 0;
802 amode.writeback = 0;
803 // fall thru to next case ....
804 case AMODE_IMM_12_PRE:
805 mMips->LBU(Rd, Rn, amode.value);
806 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
807 mMips->DADDIU(Rn, Rn, amode.value);
808 }
809 break;
810 case AMODE_IMM_12_POST:
811 mMips->LBU(Rd, Rn, 0);
812 mMips->DADDIU(Rn, Rn, amode.value);
813 break;
814 case AMODE_REG_SCALE_PRE:
815 // we only support simple base + index, no advanced modes for this one yet
816 mMips->DADDU(R_at, Rn, amode.reg);
817 mMips->LBU(Rd, R_at, 0);
818 break;
819 }
820
821}
822
823void ArmToMips64Assembler::STR(int cc, int Rd, int Rn, uint32_t offset)
824{
825 mArmPC[mInum++] = pc();
826 // work-around for ARM default address mode of immed12_pre(0)
827 if (offset > AMODE_UNSUPPORTED) offset = 0;
828 switch (offset) {
829 case 0:
830 amode.value = 0;
831 amode.writeback = 0;
832 // fall thru to next case ....
833 case AMODE_IMM_12_PRE:
834 if (Rn == ARMAssemblerInterface::SP) {
835 Rn = R_sp; // convert STR thru Arm SP to SW thru Mips SP
836 }
837 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
838 // If we will writeback, then update the index reg, then store.
839 // This correctly handles stack-push case.
840 mMips->DADDIU(Rn, Rn, amode.value);
841 mMips->SW(Rd, Rn, 0);
842 } else {
843 // No writeback so store offset by value
844 mMips->SW(Rd, Rn, amode.value);
845 }
846 break;
847 case AMODE_IMM_12_POST:
848 mMips->SW(Rd, Rn, 0);
849 mMips->DADDIU(Rn, Rn, amode.value); // post index always writes back
850 break;
851 case AMODE_REG_SCALE_PRE:
852 // we only support simple base + index, no advanced modes for this one yet
853 mMips->DADDU(R_at, Rn, amode.reg);
854 mMips->SW(Rd, R_at, 0);
855 break;
856 }
857}
858
859void ArmToMips64Assembler::STRB(int cc, int Rd, int Rn, uint32_t offset)
860{
861 mArmPC[mInum++] = pc();
862 // work-around for ARM default address mode of immed12_pre(0)
863 if (offset > AMODE_UNSUPPORTED) offset = 0;
864 switch (offset) {
865 case 0:
866 amode.value = 0;
867 amode.writeback = 0;
868 // fall thru to next case ....
869 case AMODE_IMM_12_PRE:
870 mMips->SB(Rd, Rn, amode.value);
871 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
872 mMips->DADDIU(Rn, Rn, amode.value);
873 }
874 break;
875 case AMODE_IMM_12_POST:
876 mMips->SB(Rd, Rn, 0);
877 mMips->DADDIU(Rn, Rn, amode.value);
878 break;
879 case AMODE_REG_SCALE_PRE:
880 // we only support simple base + index, no advanced modes for this one yet
881 mMips->DADDU(R_at, Rn, amode.reg);
882 mMips->SB(Rd, R_at, 0);
883 break;
884 }
885}
886
887void ArmToMips64Assembler::LDRH(int cc, int Rd, int Rn, uint32_t offset)
888{
889 mArmPC[mInum++] = pc();
890 // work-around for ARM default address mode of immed8_pre(0)
891 if (offset > AMODE_UNSUPPORTED) offset = 0;
892 switch (offset) {
893 case 0:
894 amode.value = 0;
895 // fall thru to next case ....
896 case AMODE_IMM_8_PRE: // no support yet for writeback
897 mMips->LHU(Rd, Rn, amode.value);
898 break;
899 case AMODE_IMM_8_POST:
900 mMips->LHU(Rd, Rn, 0);
901 mMips->DADDIU(Rn, Rn, amode.value);
902 break;
903 case AMODE_REG_PRE:
904 // we only support simple base +/- index
905 if (amode.reg >= 0) {
906 mMips->DADDU(R_at, Rn, amode.reg);
907 } else {
908 mMips->DSUBU(R_at, Rn, abs(amode.reg));
909 }
910 mMips->LHU(Rd, R_at, 0);
911 break;
912 }
913}
914
915void ArmToMips64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
916{
917 mArmPC[mInum++] = pc();
918 mMips->NOP2();
919 NOT_IMPLEMENTED();
920}
921
922void ArmToMips64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
923{
924 mArmPC[mInum++] = pc();
925 mMips->NOP2();
926 NOT_IMPLEMENTED();
927}
928
929void ArmToMips64Assembler::STRH(int cc, int Rd, int Rn, uint32_t offset)
930{
931 mArmPC[mInum++] = pc();
932 // work-around for ARM default address mode of immed8_pre(0)
933 if (offset > AMODE_UNSUPPORTED) offset = 0;
934 switch (offset) {
935 case 0:
936 amode.value = 0;
937 // fall thru to next case ....
938 case AMODE_IMM_8_PRE: // no support yet for writeback
939 mMips->SH(Rd, Rn, amode.value);
940 break;
941 case AMODE_IMM_8_POST:
942 mMips->SH(Rd, Rn, 0);
943 mMips->DADDIU(Rn, Rn, amode.value);
944 break;
945 case AMODE_REG_PRE:
946 // we only support simple base +/- index
947 if (amode.reg >= 0) {
948 mMips->DADDU(R_at, Rn, amode.reg);
949 } else {
950 mMips->DSUBU(R_at, Rn, abs(amode.reg));
951 }
952 mMips->SH(Rd, R_at, 0);
953 break;
954 }
955}
956
957
958
959#if 0
960#pragma mark -
961#pragma mark Block Data Transfer...
962#endif
963
964// block data transfer...
965void ArmToMips64Assembler::LDM(int cc, int dir,
966 int Rn, int W, uint32_t reg_list)
967{ // ED FD EA FA IB IA DB DA
968 // const uint8_t P[8] = { 1, 0, 1, 0, 1, 0, 1, 0 };
969 // const uint8_t U[8] = { 1, 1, 0, 0, 1, 1, 0, 0 };
970 // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
971 // (uint32_t(U[dir])<<23) | (1<<20) | (W<<21) | (Rn<<16) | reg_list;
972 mArmPC[mInum++] = pc();
973 mMips->NOP2();
974 NOT_IMPLEMENTED();
975}
976
977void ArmToMips64Assembler::STM(int cc, int dir,
978 int Rn, int W, uint32_t reg_list)
979{ // FA EA FD ED IB IA DB DA
980 // const uint8_t P[8] = { 0, 1, 0, 1, 1, 0, 1, 0 };
981 // const uint8_t U[8] = { 0, 0, 1, 1, 1, 1, 0, 0 };
982 // *mPC++ = (cc<<28) | (4<<25) | (uint32_t(P[dir])<<24) |
983 // (uint32_t(U[dir])<<23) | (0<<20) | (W<<21) | (Rn<<16) | reg_list;
984 mArmPC[mInum++] = pc();
985 mMips->NOP2();
986 NOT_IMPLEMENTED();
987}
988
989
990
991#if 0
992#pragma mark -
993#pragma mark Special...
994#endif
995
996// special...
997void ArmToMips64Assembler::SWP(int cc, int Rn, int Rd, int Rm) {
998 // *mPC++ = (cc<<28) | (2<<23) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
999 mArmPC[mInum++] = pc();
1000 mMips->NOP2();
1001 NOT_IMPLEMENTED();
1002}
1003
1004void ArmToMips64Assembler::SWPB(int cc, int Rn, int Rd, int Rm) {
1005 // *mPC++ = (cc<<28) | (2<<23) | (1<<22) | (Rn<<16) | (Rd << 12) | 0x90 | Rm;
1006 mArmPC[mInum++] = pc();
1007 mMips->NOP2();
1008 NOT_IMPLEMENTED();
1009}
1010
1011void ArmToMips64Assembler::SWI(int cc, uint32_t comment) {
1012 // *mPC++ = (cc<<28) | (0xF<<24) | comment;
1013 mArmPC[mInum++] = pc();
1014 mMips->NOP2();
1015 NOT_IMPLEMENTED();
1016}
1017
1018
1019#if 0
1020#pragma mark -
1021#pragma mark DSP instructions...
1022#endif
1023
1024// DSP instructions...
1025void ArmToMips64Assembler::PLD(int Rn, uint32_t offset) {
1026 LOG_ALWAYS_FATAL_IF(!((offset&(1<<24)) && !(offset&(1<<21))),
1027 "PLD only P=1, W=0");
1028 // *mPC++ = 0xF550F000 | (Rn<<16) | offset;
1029 mArmPC[mInum++] = pc();
1030 mMips->NOP2();
1031 NOT_IMPLEMENTED();
1032}
1033
1034void ArmToMips64Assembler::CLZ(int cc, int Rd, int Rm)
1035{
1036 mArmPC[mInum++] = pc();
1037 mMips->CLZ(Rd, Rm);
1038}
1039
1040void ArmToMips64Assembler::QADD(int cc, int Rd, int Rm, int Rn)
1041{
1042 // *mPC++ = (cc<<28) | 0x1000050 | (Rn<<16) | (Rd<<12) | Rm;
1043 mArmPC[mInum++] = pc();
1044 mMips->NOP2();
1045 NOT_IMPLEMENTED();
1046}
1047
1048void ArmToMips64Assembler::QDADD(int cc, int Rd, int Rm, int Rn)
1049{
1050 // *mPC++ = (cc<<28) | 0x1400050 | (Rn<<16) | (Rd<<12) | Rm;
1051 mArmPC[mInum++] = pc();
1052 mMips->NOP2();
1053 NOT_IMPLEMENTED();
1054}
1055
1056void ArmToMips64Assembler::QSUB(int cc, int Rd, int Rm, int Rn)
1057{
1058 // *mPC++ = (cc<<28) | 0x1200050 | (Rn<<16) | (Rd<<12) | Rm;
1059 mArmPC[mInum++] = pc();
1060 mMips->NOP2();
1061 NOT_IMPLEMENTED();
1062}
1063
1064void ArmToMips64Assembler::QDSUB(int cc, int Rd, int Rm, int Rn)
1065{
1066 // *mPC++ = (cc<<28) | 0x1600050 | (Rn<<16) | (Rd<<12) | Rm;
1067 mArmPC[mInum++] = pc();
1068 mMips->NOP2();
1069 NOT_IMPLEMENTED();
1070}
1071
1072// 16 x 16 signed multiply (like SMLAxx without the accumulate)
1073void ArmToMips64Assembler::SMUL(int cc, int xy,
1074 int Rd, int Rm, int Rs)
1075{
1076 mArmPC[mInum++] = pc();
1077
1078 // the 16 bits may be in the top or bottom half of 32-bit source reg,
1079 // as defined by the codes BB, BT, TB, TT (compressed param xy)
1080 // where x corresponds to Rm and y to Rs
1081
1082 // select half-reg for Rm
1083 if (xy & xyTB) {
1084 // use top 16-bits
1085 mMips->SRA(R_at, Rm, 16);
1086 } else {
1087 // use bottom 16, but sign-extend to 32
1088 mMips->SEH(R_at, Rm);
1089 }
1090 // select half-reg for Rs
1091 if (xy & xyBT) {
1092 // use top 16-bits
1093 mMips->SRA(R_at2, Rs, 16);
1094 } else {
1095 // use bottom 16, but sign-extend to 32
1096 mMips->SEH(R_at2, Rs);
1097 }
1098 mMips->MUL(Rd, R_at, R_at2);
1099}
1100
1101// signed 32b x 16b multiple, save top 32-bits of 48-bit result
1102void ArmToMips64Assembler::SMULW(int cc, int y,
1103 int Rd, int Rm, int Rs)
1104{
1105 mArmPC[mInum++] = pc();
1106
1107 // the selector yT or yB refers to reg Rs
1108 if (y & yT) {
1109 // zero the bottom 16-bits, with 2 shifts, it can affect result
1110 mMips->SRL(R_at, Rs, 16);
1111 mMips->SLL(R_at, R_at, 16);
1112
1113 } else {
1114 // move low 16-bit half, to high half
1115 mMips->SLL(R_at, Rs, 16);
1116 }
1117 mMips->MUH(Rd, Rm, R_at);
1118}
1119
1120// 16 x 16 signed multiply, accumulate: Rd = Rm{16} * Rs{16} + Rn
1121void ArmToMips64Assembler::SMLA(int cc, int xy,
1122 int Rd, int Rm, int Rs, int Rn)
1123{
1124 mArmPC[mInum++] = pc();
1125
1126 // the 16 bits may be in the top or bottom half of 32-bit source reg,
1127 // as defined by the codes BB, BT, TB, TT (compressed param xy)
1128 // where x corresponds to Rm and y to Rs
1129
1130 // select half-reg for Rm
1131 if (xy & xyTB) {
1132 // use top 16-bits
1133 mMips->SRA(R_at, Rm, 16);
1134 } else {
1135 // use bottom 16, but sign-extend to 32
1136 mMips->SEH(R_at, Rm);
1137 }
1138 // select half-reg for Rs
1139 if (xy & xyBT) {
1140 // use top 16-bits
1141 mMips->SRA(R_at2, Rs, 16);
1142 } else {
1143 // use bottom 16, but sign-extend to 32
1144 mMips->SEH(R_at2, Rs);
1145 }
1146
1147 mMips->MUL(R_at, R_at, R_at2);
1148 mMips->ADDU(Rd, R_at, Rn);
1149}
1150
1151void ArmToMips64Assembler::SMLAL(int cc, int xy,
1152 int RdHi, int RdLo, int Rs, int Rm)
1153{
1154 // *mPC++ = (cc<<28) | 0x1400080 | (RdHi<<16) | (RdLo<<12) | (Rs<<8) | (xy<<4) | Rm;
1155 mArmPC[mInum++] = pc();
1156 mMips->NOP2();
1157 NOT_IMPLEMENTED();
1158}
1159
1160void ArmToMips64Assembler::SMLAW(int cc, int y,
1161 int Rd, int Rm, int Rs, int Rn)
1162{
1163 // *mPC++ = (cc<<28) | 0x1200080 | (Rd<<16) | (Rn<<12) | (Rs<<8) | (y<<4) | Rm;
1164 mArmPC[mInum++] = pc();
1165 mMips->NOP2();
1166 NOT_IMPLEMENTED();
1167}
1168
1169// used by ARMv6 version of GGLAssembler::filter32
1170void ArmToMips64Assembler::UXTB16(int cc, int Rd, int Rm, int rotate)
1171{
1172 mArmPC[mInum++] = pc();
1173
1174 //Rd[31:16] := ZeroExtend((Rm ROR (8 * sh))[23:16]),
1175 //Rd[15:0] := ZeroExtend((Rm ROR (8 * sh))[7:0]). sh 0-3.
1176
1177 mMips->ROTR(R_at2, Rm, rotate * 8);
1178 mMips->LUI(R_at, 0xFF);
1179 mMips->ORI(R_at, R_at, 0xFF);
1180 mMips->AND(Rd, R_at2, R_at);
1181}
1182
1183void ArmToMips64Assembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
1184{
1185 /* Placeholder for UBFX */
1186 mArmPC[mInum++] = pc();
1187
1188 mMips->NOP2();
1189 NOT_IMPLEMENTED();
1190}
1191
1192// ----------------------------------------------------------------------------
1193// Address Processing...
1194// ----------------------------------------------------------------------------
1195
1196void ArmToMips64Assembler::ADDR_ADD(int cc,
1197 int s, int Rd, int Rn, uint32_t Op2)
1198{
1199// if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
1200// if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required
1201 dataProcessing(opADD64, cc, s, Rd, Rn, Op2);
1202}
1203
1204void ArmToMips64Assembler::ADDR_SUB(int cc,
1205 int s, int Rd, int Rn, uint32_t Op2)
1206{
1207// if(cc != AL){ NOT_IMPLEMENTED(); return;} //Not required
1208// if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required
1209 dataProcessing(opSUB64, cc, s, Rd, Rn, Op2);
1210}
1211
1212void ArmToMips64Assembler::ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset) {
1213 mArmPC[mInum++] = pc();
1214 // work-around for ARM default address mode of immed12_pre(0)
1215 if (offset > AMODE_UNSUPPORTED) offset = 0;
1216 switch (offset) {
1217 case 0:
1218 amode.value = 0;
1219 amode.writeback = 0;
1220 // fall thru to next case ....
1221 case AMODE_IMM_12_PRE:
1222 if (Rn == ARMAssemblerInterface::SP) {
1223 Rn = R_sp; // convert LDR via Arm SP to LW via Mips SP
1224 }
1225 mMips->LD(Rd, Rn, amode.value);
1226 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
1227 mMips->DADDIU(Rn, Rn, amode.value);
1228 }
1229 break;
1230 case AMODE_IMM_12_POST:
1231 if (Rn == ARMAssemblerInterface::SP) {
1232 Rn = R_sp; // convert STR thru Arm SP to STR thru Mips SP
1233 }
1234 mMips->LD(Rd, Rn, 0);
1235 mMips->DADDIU(Rn, Rn, amode.value);
1236 break;
1237 case AMODE_REG_SCALE_PRE:
1238 // we only support simple base + index, no advanced modes for this one yet
1239 mMips->DADDU(R_at, Rn, amode.reg);
1240 mMips->LD(Rd, R_at, 0);
1241 break;
1242 }
1243}
1244
1245void ArmToMips64Assembler::ADDR_STR(int cc, int Rd, int Rn, uint32_t offset) {
1246 mArmPC[mInum++] = pc();
1247 // work-around for ARM default address mode of immed12_pre(0)
1248 if (offset > AMODE_UNSUPPORTED) offset = 0;
1249 switch (offset) {
1250 case 0:
1251 amode.value = 0;
1252 amode.writeback = 0;
1253 // fall thru to next case ....
1254 case AMODE_IMM_12_PRE:
1255 if (Rn == ARMAssemblerInterface::SP) {
1256 Rn = R_sp; // convert STR thru Arm SP to SW thru Mips SP
1257 }
1258 if (amode.writeback) { // OPTIONAL writeback on pre-index mode
1259 // If we will writeback, then update the index reg, then store.
1260 // This correctly handles stack-push case.
1261 mMips->DADDIU(Rn, Rn, amode.value);
1262 mMips->SD(Rd, Rn, 0);
1263 } else {
1264 // No writeback so store offset by value
1265 mMips->SD(Rd, Rn, amode.value);
1266 }
1267 break;
1268 case AMODE_IMM_12_POST:
1269 mMips->SD(Rd, Rn, 0);
1270 mMips->DADDIU(Rn, Rn, amode.value); // post index always writes back
1271 break;
1272 case AMODE_REG_SCALE_PRE:
1273 // we only support simple base + index, no advanced modes for this one yet
1274 mMips->DADDU(R_at, Rn, amode.reg);
1275 mMips->SD(Rd, R_at, 0);
1276 break;
1277 }
1278}
1279
1280#if 0
1281#pragma mark -
1282#pragma mark MIPS Assembler...
1283#endif
1284
1285
1286//**************************************************************************
1287//**************************************************************************
1288//**************************************************************************
1289
1290
1291/* MIPS64 assembler
1292** this is a subset of mips64r6, targeted specifically at ARM instruction
1293** replacement in the pixelflinger/codeflinger code.
1294**
1295** This class is extended from MIPSAssembler class and overrides only
1296** MIPS64r6 specific stuff.
1297*/
1298
1299MIPS64Assembler::MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent)
1300 : mParent(parent),
1301 MIPSAssembler::MIPSAssembler(assembly, NULL)
1302{
1303}
1304
1305MIPS64Assembler::MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent)
1306 : mParent(parent),
1307 MIPSAssembler::MIPSAssembler(NULL, NULL)
1308{
1309 mBase = mPC = (uint32_t *)assembly;
1310}
1311
1312MIPS64Assembler::~MIPS64Assembler()
1313{
1314}
1315
1316void MIPS64Assembler::reset()
1317{
1318 if (mAssembly != NULL) {
1319 mBase = mPC = (uint32_t *)mAssembly->base();
1320 } else {
1321 mPC = mBase = base();
1322 }
1323 mBranchTargets.clear();
1324 mLabels.clear();
1325 mLabelsInverseMapping.clear();
1326 mComments.clear();
1327}
1328
1329
1330void MIPS64Assembler::disassemble(const char* name)
1331{
1332 char di_buf[140];
1333
1334 bool arm_disasm_fmt = (mParent->mArmDisassemblyBuffer == NULL) ? false : true;
1335
1336 typedef char dstr[40];
1337 dstr *lines = (dstr *)mParent->mArmDisassemblyBuffer;
1338
1339 if (mParent->mArmDisassemblyBuffer != NULL) {
1340 for (int i=0; i<mParent->mArmInstrCount; ++i) {
1341 string_detab(lines[i]);
1342 }
1343 }
1344
1345 // iArm is an index to Arm instructions 1...n for this assembly sequence
1346 // mArmPC[iArm] holds the value of the Mips-PC for the first MIPS
1347 // instruction corresponding to that Arm instruction number
1348
1349 int iArm = 0;
1350 size_t count = pc()-base();
1351 uint32_t* mipsPC = base();
1352
1353 while (count--) {
1354 ssize_t label = mLabelsInverseMapping.indexOfKey(mipsPC);
1355 if (label >= 0) {
1356 ALOGW("%s:\n", mLabelsInverseMapping.valueAt(label));
1357 }
1358 ssize_t comment = mComments.indexOfKey(mipsPC);
1359 if (comment >= 0) {
1360 ALOGW("; %s\n", mComments.valueAt(comment));
1361 }
1362 ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt);
1363 string_detab(di_buf);
1364 string_pad(di_buf, 30);
1365 ALOGW("%08lx: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf);
1366 mipsPC++;
1367 }
1368}
1369
1370void MIPS64Assembler::fix_branches()
1371{
1372 // fixup all the branches
1373 size_t count = mBranchTargets.size();
1374 while (count--) {
1375 const branch_target_t& bt = mBranchTargets[count];
1376 uint32_t* target_pc = mLabels.valueFor(bt.label);
1377 LOG_ALWAYS_FATAL_IF(!target_pc,
1378 "error resolving branch targets, target_pc is null");
1379 int32_t offset = int32_t(target_pc - (bt.pc+1));
1380 *bt.pc |= offset & 0x00FFFF;
1381 }
1382}
1383
1384void MIPS64Assembler::DADDU(int Rd, int Rs, int Rt)
1385{
1386 *mPC++ = (spec_op<<OP_SHF) | (daddu_fn<<FUNC_SHF)
1387 | (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF);
1388}
1389
1390void MIPS64Assembler::DADDIU(int Rt, int Rs, int16_t imm)
1391{
1392 *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | (imm & MSK_16);
1393}
1394
1395void MIPS64Assembler::DSUBU(int Rd, int Rs, int Rt)
1396{
1397 *mPC++ = (spec_op<<OP_SHF) | (dsubu_fn<<FUNC_SHF) |
1398 (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
1399}
1400
1401void MIPS64Assembler::DSUBIU(int Rt, int Rs, int16_t imm) // really addiu(d, s, -j)
1402{
1403 *mPC++ = (daddiu_op<<OP_SHF) | (Rt<<RT_SHF) | (Rs<<RS_SHF) | ((-imm) & MSK_16);
1404}
1405
1406void MIPS64Assembler::MUL(int Rd, int Rs, int Rt)
1407{
1408 *mPC++ = (spec_op<<OP_SHF) | (mul_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) |
1409 (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
1410}
1411
1412void MIPS64Assembler::MUH(int Rd, int Rs, int Rt)
1413{
1414 *mPC++ = (spec_op<<OP_SHF) | (muh_fn<<RE_SHF) | (sop30_fn<<FUNC_SHF) |
1415 (Rs<<RS_SHF) | (Rt<<RT_SHF) | (Rd<<RD_SHF) ;
1416}
1417
1418void MIPS64Assembler::CLO(int Rd, int Rs)
1419{
1420 *mPC++ = (spec_op<<OP_SHF) | (17<<FUNC_SHF) |
1421 (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF);
1422}
1423
1424void MIPS64Assembler::CLZ(int Rd, int Rs)
1425{
1426 *mPC++ = (spec_op<<OP_SHF) | (16<<FUNC_SHF) |
1427 (Rd<<RD_SHF) | (Rs<<RS_SHF) | (1<<RE_SHF);
1428}
1429
1430void MIPS64Assembler::LD(int Rt, int Rbase, int16_t offset)
1431{
1432 *mPC++ = (ld_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
1433}
1434
1435void MIPS64Assembler::SD(int Rt, int Rbase, int16_t offset)
1436{
1437 *mPC++ = (sd_op<<OP_SHF) | (Rbase<<RS_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
1438}
1439
1440void MIPS64Assembler::LUI(int Rt, int16_t offset)
1441{
1442 *mPC++ = (aui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16);
1443}
1444
1445
1446void MIPS64Assembler::JR(int Rs)
1447{
1448 *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jalr_fn << FUNC_SHF);
1449 MIPS64Assembler::NOP();
1450}
1451
1452}; // namespace android:
diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.h b/libpixelflinger/codeflinger/MIPS64Assembler.h
new file mode 100644
index 000000000..6c760f4ab
--- /dev/null
+++ b/libpixelflinger/codeflinger/MIPS64Assembler.h
@@ -0,0 +1,429 @@
1/* libs/pixelflinger/codeflinger/MIPS64Assembler.h
2**
3** Copyright 2015, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#ifndef ANDROID_MIPS64ASSEMBLER_H
19#define ANDROID_MIPS64ASSEMBLER_H
20
21#include <stdint.h>
22#include <sys/types.h>
23
24#include "tinyutils/KeyedVector.h"
25#include "tinyutils/Vector.h"
26#include "tinyutils/smartpointer.h"
27
28#include "ARMAssemblerInterface.h"
29#include "MIPSAssembler.h"
30#include "CodeCache.h"
31
32namespace android {
33
34class MIPS64Assembler; // forward reference
35
36// this class mimics ARMAssembler interface
37// intent is to translate each ARM instruction to 1 or more MIPS instr
38// implementation calls MIPS64Assembler class to generate mips code
39class ArmToMips64Assembler : public ARMAssemblerInterface
40{
41public:
42 ArmToMips64Assembler(const sp<Assembly>& assembly,
43 char *abuf = 0, int linesz = 0, int instr_count = 0);
44 ArmToMips64Assembler(void* assembly);
45 virtual ~ArmToMips64Assembler();
46
47 uint32_t* base() const;
48 uint32_t* pc() const;
49 void disassemble(const char* name);
50
51 virtual void reset();
52
53 virtual int generate(const char* name);
54 virtual int getCodegenArch();
55
56 virtual void prolog();
57 virtual void epilog(uint32_t touched);
58 virtual void comment(const char* string);
59 // for testing purposes
60 void fix_branches();
61 void set_condition(int mode, int R1, int R2);
62
63
64 // -----------------------------------------------------------------------
65 // shifters and addressing modes
66 // -----------------------------------------------------------------------
67
68 // shifters...
69 virtual bool isValidImmediate(uint32_t immed);
70 virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
71
72 virtual uint32_t imm(uint32_t immediate);
73 virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
74 virtual uint32_t reg_rrx(int Rm);
75 virtual uint32_t reg_reg(int Rm, int type, int Rs);
76
77 // addressing modes...
78 // LDR(B)/STR(B)/PLD
79 // (immediate and Rm can be negative, which indicates U=0)
80 virtual uint32_t immed12_pre(int32_t immed12, int W=0);
81 virtual uint32_t immed12_post(int32_t immed12);
82 virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
83 virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
84
85 // LDRH/LDRSB/LDRSH/STRH
86 // (immediate and Rm can be negative, which indicates U=0)
87 virtual uint32_t immed8_pre(int32_t immed8, int W=0);
88 virtual uint32_t immed8_post(int32_t immed8);
89 virtual uint32_t reg_pre(int Rm, int W=0);
90 virtual uint32_t reg_post(int Rm);
91
92
93
94
95 virtual void dataProcessing(int opcode, int cc, int s,
96 int Rd, int Rn,
97 uint32_t Op2);
98 virtual void MLA(int cc, int s,
99 int Rd, int Rm, int Rs, int Rn);
100 virtual void MUL(int cc, int s,
101 int Rd, int Rm, int Rs);
102 virtual void UMULL(int cc, int s,
103 int RdLo, int RdHi, int Rm, int Rs);
104 virtual void UMUAL(int cc, int s,
105 int RdLo, int RdHi, int Rm, int Rs);
106 virtual void SMULL(int cc, int s,
107 int RdLo, int RdHi, int Rm, int Rs);
108 virtual void SMUAL(int cc, int s,
109 int RdLo, int RdHi, int Rm, int Rs);
110
111 virtual void B(int cc, uint32_t* pc);
112 virtual void BL(int cc, uint32_t* pc);
113 virtual void BX(int cc, int Rn);
114 virtual void label(const char* theLabel);
115 virtual void B(int cc, const char* label);
116 virtual void BL(int cc, const char* label);
117
118 virtual uint32_t* pcForLabel(const char* label);
119
120 virtual void LDR (int cc, int Rd,
121 int Rn, uint32_t offset = 0);
122 virtual void LDRB(int cc, int Rd,
123 int Rn, uint32_t offset = 0);
124 virtual void STR (int cc, int Rd,
125 int Rn, uint32_t offset = 0);
126 virtual void STRB(int cc, int Rd,
127 int Rn, uint32_t offset = 0);
128 virtual void LDRH (int cc, int Rd,
129 int Rn, uint32_t offset = 0);
130 virtual void LDRSB(int cc, int Rd,
131 int Rn, uint32_t offset = 0);
132 virtual void LDRSH(int cc, int Rd,
133 int Rn, uint32_t offset = 0);
134 virtual void STRH (int cc, int Rd,
135 int Rn, uint32_t offset = 0);
136
137 virtual void LDM(int cc, int dir,
138 int Rn, int W, uint32_t reg_list);
139 virtual void STM(int cc, int dir,
140 int Rn, int W, uint32_t reg_list);
141
142 virtual void SWP(int cc, int Rn, int Rd, int Rm);
143 virtual void SWPB(int cc, int Rn, int Rd, int Rm);
144 virtual void SWI(int cc, uint32_t comment);
145
146 virtual void PLD(int Rn, uint32_t offset);
147 virtual void CLZ(int cc, int Rd, int Rm);
148 virtual void QADD(int cc, int Rd, int Rm, int Rn);
149 virtual void QDADD(int cc, int Rd, int Rm, int Rn);
150 virtual void QSUB(int cc, int Rd, int Rm, int Rn);
151 virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
152 virtual void SMUL(int cc, int xy,
153 int Rd, int Rm, int Rs);
154 virtual void SMULW(int cc, int y,
155 int Rd, int Rm, int Rs);
156 virtual void SMLA(int cc, int xy,
157 int Rd, int Rm, int Rs, int Rn);
158 virtual void SMLAL(int cc, int xy,
159 int RdHi, int RdLo, int Rs, int Rm);
160 virtual void SMLAW(int cc, int y,
161 int Rd, int Rm, int Rs, int Rn);
162
163 // byte/half word extract...
164 virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
165
166 // bit manipulation...
167 virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
168
169 // Address loading/storing/manipulation
170 virtual void ADDR_LDR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
171 virtual void ADDR_STR(int cc, int Rd, int Rn, uint32_t offset = __immed12_pre(0));
172 virtual void ADDR_ADD(int cc, int s, int Rd, int Rn, uint32_t Op2);
173 virtual void ADDR_SUB(int cc, int s, int Rd, int Rn, uint32_t Op2);
174
175 // this is some crap to share is MIPS64Assembler class for debug
176 char * mArmDisassemblyBuffer;
177 int mArmLineLength;
178 int mArmInstrCount;
179
180 int mInum; // current arm instuction number (0..n)
181 uint32_t** mArmPC; // array: PC for 1st mips instr of
182 // each translated ARM instr
183
184
185private:
186 ArmToMips64Assembler(const ArmToMips64Assembler& rhs);
187 ArmToMips64Assembler& operator = (const ArmToMips64Assembler& rhs);
188
189 void init_conditional_labels(void);
190
191 void protectConditionalOperands(int Rd);
192
193 // reg__tmp set to MIPS AT, reg 1
194 int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
195
196 sp<Assembly> mAssembly;
197 MIPS64Assembler* mMips;
198
199
200 enum misc_constants_t {
201 ARM_MAX_INSTUCTIONS = 512 // based on ASSEMBLY_SCRATCH_SIZE
202 };
203
204 enum {
205 SRC_REG = 0,
206 SRC_IMM,
207 SRC_ERROR = -1
208 };
209
210 enum addr_modes {
211 // start above the range of legal mips reg #'s (0-31)
212 AMODE_REG = 0x20,
213 AMODE_IMM, AMODE_REG_IMM, // for data processing
214 AMODE_IMM_12_PRE, AMODE_IMM_12_POST, // for load/store
215 AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
216 AMODE_IMM_8_POST, AMODE_REG_PRE,
217 AMODE_UNSUPPORTED
218 };
219
220 struct addr_mode_t { // address modes for current ARM instruction
221 int reg;
222 int stype;
223 uint32_t value;
224 bool writeback; // writeback the adr reg after modification
225 } amode;
226
227 enum cond_types {
228 CMP_COND = 1,
229 SBIT_COND
230 };
231
232 struct cond_mode_t { // conditional-execution info for current ARM instruction
233 cond_types type;
234 int r1;
235 int r2;
236 int labelnum;
237 char label[100][10];
238 } cond;
239};
240
241
242
243
244// ----------------------------------------------------------------------------
245// ----------------------------------------------------------------------------
246// ----------------------------------------------------------------------------
247
248// This is the basic MIPS64 assembler, which just creates the opcodes in memory.
249// All the more complicated work is done in ArmToMips64Assember above.
250// Inherits MIPSAssembler class, and overrides only MIPS64r6 specific stuff
251
252class MIPS64Assembler : public MIPSAssembler
253{
254public:
255 MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent);
256 MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent);
257 virtual ~MIPS64Assembler();
258
259 virtual void reset();
260 virtual void disassemble(const char* name);
261
262 void fix_branches();
263
264 // ------------------------------------------------------------------------
265 // MIPS64AssemblerInterface...
266 // ------------------------------------------------------------------------
267
268#if 0
269#pragma mark -
270#pragma mark Arithmetic...
271#endif
272
273 void DADDU(int Rd, int Rs, int Rt);
274 void DADDIU(int Rt, int Rs, int16_t imm);
275 void DSUBU(int Rd, int Rs, int Rt);
276 void DSUBIU(int Rt, int Rs, int16_t imm);
277 virtual void MUL(int Rd, int Rs, int Rt);
278 void MUH(int Rd, int Rs, int Rt);
279
280#if 0
281#pragma mark -
282#pragma mark Logical...
283#endif
284
285 virtual void CLO(int Rd, int Rs);
286 virtual void CLZ(int Rd, int Rs);
287
288#if 0
289#pragma mark -
290#pragma mark Load/store...
291#endif
292
293 void LD(int Rt, int Rbase, int16_t offset);
294 void SD(int Rt, int Rbase, int16_t offset);
295 virtual void LUI(int Rt, int16_t offset);
296
297#if 0
298#pragma mark -
299#pragma mark Branch...
300#endif
301
302 void JR(int Rs);
303
304
305protected:
306 // void string_detab(char *s);
307 // void string_pad(char *s, int padded_len);
308
309 ArmToMips64Assembler *mParent;
310 sp<Assembly> mAssembly;
311 uint32_t* mBase;
312 uint32_t* mPC;
313 uint32_t* mPrologPC;
314 int64_t mDuration;
315#if defined(WITH_LIB_HARDWARE)
316 bool mQemuTracing;
317#endif
318
319 struct branch_target_t {
320 inline branch_target_t() : label(0), pc(0) { }
321 inline branch_target_t(const char* l, uint32_t* p)
322 : label(l), pc(p) { }
323 const char* label;
324 uint32_t* pc;
325 };
326
327 Vector<branch_target_t> mBranchTargets;
328 KeyedVector< const char*, uint32_t* > mLabels;
329 KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
330 KeyedVector< uint32_t*, const char* > mComments;
331
332
333 // opcode field of all instructions
334 enum opcode_field {
335 spec_op, regimm_op, j_op, jal_op, // 0x00 - 0x03
336 beq_op, bne_op, pop06_op, pop07_op, // 0x04 - 0x07
337 pop10_op, addiu_op, slti_op, sltiu_op, // 0x08 - 0x0b
338 andi_op, ori_op, xori_op, aui_op, // 0x0c - 0x0f
339 cop0_op, cop1_op, cop2_op, rsrv_opc_0, // 0x10 - 0x13
340 rsrv_opc_1, rsrv_opc_2, pop26_op, pop27_op, // 0x14 - 0x17
341 pop30_op, daddiu_op, rsrv_opc_3, rsrv_opc_4, // 0x18 - 0x1b
342 rsrv_opc_5, daui_op, msa_op, spec3_op, // 0x1c - 0x1f
343 lb_op, lh_op, rsrv_opc_6, lw_op, // 0x20 - 0x23
344 lbu_op, lhu_op, rsrv_opc_7, lwu_op, // 0x24 - 0x27
345 sb_op, sh_op, rsrv_opc_8, sw_op, // 0x28 - 0x2b
346 rsrv_opc_9, rsrv_opc_10, rsrv_opc_11, rsrv_opc_12, // 0x2c - 0x2f
347 rsrv_opc_13, lwc1_op, bc_op, rsrv_opc_14, // 0x2c - 0x2f
348 rsrv_opc_15, ldc1_op, pop66_op, ld_op, // 0x30 - 0x33
349 rsrv_opc_16, swc1_op, balc_op, pcrel_op, // 0x34 - 0x37
350 rsrv_opc_17, sdc1_op, pop76_op, sd_op // 0x38 - 0x3b
351 };
352
353
354 // func field for special opcode
355 enum func_spec_op {
356 sll_fn, rsrv_spec_0, srl_fn, sra_fn,
357 sllv_fn, lsa_fn, srlv_fn, srav_fn,
358 rsrv_spec_1, jalr_fn, rsrv_spec_2, rsrv_spec_3,
359 syscall_fn, break_fn, sdbbp_fn, sync_fn,
360 clz_fn, clo_fn, dclz_fn, dclo_fn,
361 dsllv_fn, dlsa_fn, dsrlv_fn, dsrav_fn,
362 sop30_fn, sop31_fn, sop32_fn, sop33_fn,
363 sop34_fn, sop35_fn, sop36_fn, sop37_fn,
364 add_fn, addu_fn, sub_fn, subu_fn,
365 and_fn, or_fn, xor_fn, nor_fn,
366 rsrv_spec_4, rsrv_spec_5, slt_fn, sltu_fn,
367 dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
368 tge_fn, tgeu_fn, tlt_fn, tltu_fn,
369 teq_fn, seleqz_fn, tne_fn, selnez_fn,
370 dsll_fn, rsrv_spec_6, dsrl_fn, dsra_fn,
371 dsll32_fn, rsrv_spec_7, dsrl32_fn, dsra32_fn
372 };
373
374 // func field for spec3 opcode
375 enum func_spec3_op {
376 ext_fn, dextm_fn, dextu_fn, dext_fn,
377 ins_fn, dinsm_fn, dinsu_fn, dins_fn,
378 cachee_fn = 0x1b, sbe_fn, she_fn, sce_fn, swe_fn,
379 bshfl_fn, prefe_fn = 0x23, dbshfl_fn, cache_fn, sc_fn, scd_fn,
380 lbue_fn, lhue_fn, lbe_fn = 0x2c, lhe_fn, lle_fn, lwe_fn,
381 pref_fn = 0x35, ll_fn, lld_fn, rdhwr_fn = 0x3b
382 };
383
384 // sa field for spec3 opcodes, with BSHFL function
385 enum func_spec3_bshfl {
386 bitswap_fn,
387 wsbh_fn = 0x02,
388 dshd_fn = 0x05,
389 seb_fn = 0x10,
390 seh_fn = 0x18
391 };
392
393 // rt field of regimm opcodes.
394 enum regimm_fn {
395 bltz_fn, bgez_fn,
396 dahi_fn = 0x6,
397 nal_fn = 0x10, bal_fn, bltzall_fn, bgezall_fn,
398 sigrie_fn = 0x17,
399 dati_fn = 0x1e, synci_fn
400 };
401
402 enum muldiv_fn {
403 mul_fn = 0x02, muh_fn
404 };
405
406 enum mips_inst_shifts {
407 OP_SHF = 26,
408 JTARGET_SHF = 0,
409 RS_SHF = 21,
410 RT_SHF = 16,
411 RD_SHF = 11,
412 RE_SHF = 6,
413 SA_SHF = RE_SHF, // synonym
414 IMM_SHF = 0,
415 FUNC_SHF = 0,
416
417 // mask values
418 MSK_16 = 0xffff,
419
420
421 CACHEOP_SHF = 18,
422 CACHESEL_SHF = 16,
423 };
424};
425
426
427}; // namespace android
428
429#endif //ANDROID_MIPS64ASSEMBLER_H
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index a88d2fe00..daa231fe0 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -1358,7 +1358,7 @@ void MIPSAssembler::disassemble(const char* name)
1358 ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); 1358 ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt);
1359 string_detab(di_buf); 1359 string_detab(di_buf);
1360 string_pad(di_buf, 30); 1360 string_pad(di_buf, 30);
1361 ALOGW("%08x: %08x %s", uint32_t(mipsPC), uint32_t(*mipsPC), di_buf); 1361 ALOGW("%08x: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf);
1362 mipsPC++; 1362 mipsPC++;
1363 } 1363 }
1364} 1364}
@@ -1407,7 +1407,7 @@ int MIPSAssembler::generate(const char* name)
1407 1407
1408#if defined(WITH_LIB_HARDWARE) 1408#if defined(WITH_LIB_HARDWARE)
1409 if (__builtin_expect(mQemuTracing, 0)) { 1409 if (__builtin_expect(mQemuTracing, 0)) {
1410 int err = qemu_add_mapping(int(base()), name); 1410 int err = qemu_add_mapping(uintptr_t(base()), name);
1411 mQemuTracing = (err >= 0); 1411 mQemuTracing = (err >= 0);
1412 } 1412 }
1413#endif 1413#endif
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h
index 430ab064c..68a2b4fe2 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.h
+++ b/libpixelflinger/codeflinger/MIPSAssembler.h
@@ -244,20 +244,20 @@ public:
244 MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent); 244 MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent);
245 virtual ~MIPSAssembler(); 245 virtual ~MIPSAssembler();
246 246
247 uint32_t* base() const; 247 virtual uint32_t* base() const;
248 uint32_t* pc() const; 248 virtual uint32_t* pc() const;
249 void reset(); 249 virtual void reset();
250 250
251 void disassemble(const char* name); 251 virtual void disassemble(const char* name);
252 252
253 void prolog(); 253 virtual void prolog();
254 void epilog(uint32_t touched); 254 virtual void epilog(uint32_t touched);
255 int generate(const char* name); 255 virtual int generate(const char* name);
256 void comment(const char* string); 256 virtual void comment(const char* string);
257 void label(const char* string); 257 virtual void label(const char* string);
258 258
259 // valid only after generate() has been called 259 // valid only after generate() has been called
260 uint32_t* pcForLabel(const char* label); 260 virtual uint32_t* pcForLabel(const char* label);
261 261
262 262
263 // ------------------------------------------------------------------------ 263 // ------------------------------------------------------------------------
@@ -399,9 +399,9 @@ public:
399 399
400 400
401 401
402private: 402protected:
403 void string_detab(char *s); 403 virtual void string_detab(char *s);
404 void string_pad(char *s, int padded_len); 404 virtual void string_pad(char *s, int padded_len);
405 405
406 ArmToMipsAssembler *mParent; 406 ArmToMipsAssembler *mParent;
407 sp<Assembly> mAssembly; 407 sp<Assembly> mAssembly;
@@ -537,7 +537,11 @@ private:
537enum mips_regnames { 537enum mips_regnames {
538 R_zero = 0, 538 R_zero = 0,
539 R_at, R_v0, R_v1, R_a0, R_a1, R_a2, R_a3, 539 R_at, R_v0, R_v1, R_a0, R_a1, R_a2, R_a3,
540#if __mips_isa_rev < 6
540 R_t0, R_t1, R_t2, R_t3, R_t4, R_t5, R_t6, R_t7, 541 R_t0, R_t1, R_t2, R_t3, R_t4, R_t5, R_t6, R_t7,
542#else
543 R_a4, R_a5, R_a6, R_a7, R_t0, R_t1, R_t2, R_t3,
544#endif
541 R_s0, R_s1, R_s2, R_s3, R_s4, R_s5, R_s6, R_s7, 545 R_s0, R_s1, R_s2, R_s3, R_s4, R_s5, R_s6, R_s7,
542 R_t8, R_t9, R_k0, R_k1, R_gp, R_sp, R_s8, R_ra, 546 R_t8, R_t9, R_k0, R_k1, R_gp, R_sp, R_s8, R_ra,
543 R_lr = R_s8, 547 R_lr = R_s8,
diff --git a/libpixelflinger/codeflinger/mips64_disassem.c b/libpixelflinger/codeflinger/mips64_disassem.c
new file mode 100644
index 000000000..44b7fe7cd
--- /dev/null
+++ b/libpixelflinger/codeflinger/mips64_disassem.c
@@ -0,0 +1,582 @@
1/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
35 */
36
37#include <stdio.h>
38#include <stdint.h>
39#include <stdarg.h>
40#include <stdbool.h>
41#include <sys/cdefs.h>
42
43#include <sys/types.h>
44#include "mips_opcode.h"
45
46#include <cutils/log.h>
47
48static char *sprintf_buffer;
49static int sprintf_buf_len;
50
51
52typedef uint64_t db_addr_t;
53static void db_printf(const char* fmt, ...);
54
55static const char * const op_name[64] = {
56/* 0 */ "spec", "bcond", "j", "jal", "beq", "bne", "blez", "bgtz",
57/* 8 */ "pop10", "addiu", "slti", "sltiu", "andi", "ori", "xori", "aui",
58/*16 */ "cop0", "cop1", "cop2", "?", "?", "?", "pop26", "pop27",
59/*24 */ "pop30", "daddiu", "?", "?", "?", "daui", "msa", "op37",
60/*32 */ "lb", "lh", "?", "lw", "lbu", "lhu", "?", "lwu",
61/*40 */ "sb", "sh", "?", "sw", "?", "?", "?", "?",
62/*48 */ "?", "lwc1", "bc", "?", "?", "ldc1", "pop66", "ld",
63/*56 */ "?", "swc1", "balc", "pcrel", "?", "sdc1", "pop76", "sd"
64};
65
66static const char * const spec_name[64] = {
67/* 0 */ "sll", "?", "srl", "sra", "sllv", "?", "srlv", "srav",
68/* 8 */ "?", "jalr", "?", "?", "syscall", "break", "sdbpp", "sync",
69/*16 */ "clz", "clo", "dclz", "dclo", "dsllv", "dlsa", "dsrlv", "dsrav",
70/*24 */ "sop30", "sop31", "sop32", "sop33", "sop34", "sop35", "sop36", "sop37",
71/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
72/*40 */ "?", "?", "slt", "sltu", "dadd", "daddu", "dsub", "dsubu",
73/*48 */ "tge", "tgeu", "tlt", "tltu", "teq", "seleqz", "tne", "selnez",
74/*56 */ "dsll", "?", "dsrl", "dsra", "dsll32", "?", "dsrl32", "dsra32"
75};
76
77static const char * const bcond_name[32] = {
78/* 0 */ "bltz", "bgez", "?", "?", "?", "?", "dahi", "?",
79/* 8 */ "?", "?", "?", "?", "?", "?", "?", "?",
80/*16 */ "nal", "bal", "?", "?", "?", "?", "?", "sigrie",
81/*24 */ "?", "?", "?", "?", "?", "?", "dati", "synci",
82};
83
84static const char * const cop1_name[64] = {
85/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
86/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
87/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
88/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
89/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
90/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
91/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
92 "fcmp.ole","fcmp.ule",
93/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
94 "fcmp.le","fcmp.ngt"
95};
96
97static const char * const fmt_name[16] = {
98 "s", "d", "e", "fmt3",
99 "w", "fmt5", "fmt6", "fmt7",
100 "fmt8", "fmt9", "fmta", "fmtb",
101 "fmtc", "fmtd", "fmte", "fmtf"
102};
103
104static char * const mips_reg_name[32] = {
105 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
106 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
107 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
108 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
109};
110
111static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM code
112 "zero", "at", "r0", "r1", "r2", "r3", "r4", "r5",
113 "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13",
114 "r14", "r15", "at2", "cmp", "s4", "s5", "s6", "s7",
115 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
116};
117
118static char ** reg_name = &mips_reg_name[0];
119
120static const char * const c0_opname[64] = {
121 "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
122 "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
123 "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
124 "eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
125 "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
126 "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
127 "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
128 "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
129};
130
131static const char * const c0_reg[32] = {
132 "index", "random", "tlblo0", "tlblo1",
133 "context", "pagemask", "wired", "cp0r7",
134 "badvaddr", "count", "tlbhi", "compare",
135 "status", "cause", "epc", "prid",
136 "config", "lladdr", "watchlo", "watchhi",
137 "xcontext", "cp0r21", "cp0r22", "debug",
138 "depc", "perfcnt", "ecc", "cacheerr",
139 "taglo", "taghi", "errepc", "desave"
140};
141
142static void print_addr(db_addr_t);
143db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
144
145
146/*
147 * Disassemble instruction 'insn' nominally at 'loc'.
148 * 'loc' may in fact contain a breakpoint instruction.
149 */
150static db_addr_t
151db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
152{
153 bool bdslot = false;
154 InstFmt i;
155
156 i.word = insn;
157
158 switch (i.JType.op) {
159 case OP_SPECIAL:
160 if (i.word == 0) {
161 db_printf("nop");
162 break;
163 }
164 if (i.word == 0x0080) {
165 db_printf("NIY");
166 break;
167 }
168 if (i.word == 0x00c0) {
169 db_printf("NOT IMPL");
170 break;
171 }
172 /* Special cases --------------------------------------------------
173 * "addu" is a "move" only in 32-bit mode. What's the correct
174 * answer - never decode addu/daddu as "move"?
175 */
176 if ( (i.RType.func == OP_ADDU && i.RType.rt == 0) ||
177 (i.RType.func == OP_OR && i.RType.rt == 0) ) {
178 db_printf("move\t%s,%s",
179 reg_name[i.RType.rd],
180 reg_name[i.RType.rs]);
181 break;
182 }
183
184 if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
185 db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
186 reg_name[i.RType.rt], i.RType.shamt);
187 break;
188 }
189 if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
190 db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
191 reg_name[i.RType.rt], reg_name[i.RType.rs]);
192 break;
193 }
194
195 if (i.RType.func == OP_SOP30) {
196 if (i.RType.shamt == OP_MUL) {
197 db_printf("mul");
198 } else if (i.RType.shamt == OP_MUH) {
199 db_printf("muh");
200 }
201 db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
202 reg_name[i.RType.rs], reg_name[i.RType.rt]);
203 break;
204 }
205 if (i.RType.func == OP_SOP31) {
206 if (i.RType.shamt == OP_MUL) {
207 db_printf("mulu");
208 } else if (i.RType.shamt == OP_MUH) {
209 db_printf("muhu");
210 }
211 db_printf("\t%s,%s,%s", reg_name[i.RType.rd],
212 reg_name[i.RType.rs], reg_name[i.RType.rt]);
213 break;
214 }
215
216 if (i.RType.func == OP_JALR && i.RType.rd == 0) {
217 db_printf("jr\t%s", reg_name[i.RType.rs]);
218 bdslot = true;
219 break;
220 }
221
222 db_printf("%s", spec_name[i.RType.func]);
223 switch (i.RType.func) {
224 case OP_SLL:
225 case OP_SRL:
226 case OP_SRA:
227 case OP_DSLL:
228
229 case OP_DSRL:
230 case OP_DSRA:
231 case OP_DSLL32:
232 case OP_DSRL32:
233 case OP_DSRA32:
234 db_printf("\t%s,%s,%d",
235 reg_name[i.RType.rd],
236 reg_name[i.RType.rt],
237 i.RType.shamt);
238 break;
239
240 case OP_SLLV:
241 case OP_SRLV:
242 case OP_SRAV:
243 case OP_DSLLV:
244 case OP_DSRLV:
245 case OP_DSRAV:
246 db_printf("\t%s,%s,%s",
247 reg_name[i.RType.rd],
248 reg_name[i.RType.rt],
249 reg_name[i.RType.rs]);
250 break;
251
252 case OP_CLZ:
253 case OP_CLO:
254 case OP_DCLZ:
255 case OP_DCLO:
256 db_printf("\t%s,%s",
257 reg_name[i.RType.rd],
258 reg_name[i.RType.rs]);
259 break;
260
261 case OP_JALR:
262 db_printf("\t");
263 if (i.RType.rd != 31) {
264 db_printf("%s,", reg_name[i.RType.rd]);
265 }
266 db_printf("%s", reg_name[i.RType.rs]);
267 bdslot = true;
268 break;
269
270 case OP_SYSCALL:
271 case OP_SYNC:
272 break;
273
274 case OP_BREAK:
275 db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
276 break;
277
278 default:
279 db_printf("\t%s,%s,%s",
280 reg_name[i.RType.rd],
281 reg_name[i.RType.rs],
282 reg_name[i.RType.rt]);
283 }
284 break;
285
286 case OP_SPECIAL3:
287 if (i.RType.func == OP_EXT)
288 db_printf("ext\t%s,%s,%d,%d",
289 reg_name[i.RType.rt],
290 reg_name[i.RType.rs],
291 i.RType.shamt,
292 i.RType.rd+1);
293 else if (i.RType.func == OP_DEXT)
294 db_printf("dext\t%s,%s,%d,%d",
295 reg_name[i.RType.rt],
296 reg_name[i.RType.rs],
297 i.RType.shamt,
298 i.RType.rd+1);
299 else if (i.RType.func == OP_DEXTM)
300 db_printf("dextm\t%s,%s,%d,%d",
301 reg_name[i.RType.rt],
302 reg_name[i.RType.rs],
303 i.RType.shamt,
304 i.RType.rd+33);
305 else if (i.RType.func == OP_DEXTU)
306 db_printf("dextu\t%s,%s,%d,%d",
307 reg_name[i.RType.rt],
308 reg_name[i.RType.rs],
309 i.RType.shamt+32,
310 i.RType.rd+1);
311 else if (i.RType.func == OP_INS)
312 db_printf("ins\t%s,%s,%d,%d",
313 reg_name[i.RType.rt],
314 reg_name[i.RType.rs],
315 i.RType.shamt,
316 i.RType.rd-i.RType.shamt+1);
317 else if (i.RType.func == OP_DINS)
318 db_printf("dins\t%s,%s,%d,%d",
319 reg_name[i.RType.rt],
320 reg_name[i.RType.rs],
321 i.RType.shamt,
322 i.RType.rd-i.RType.shamt+1);
323 else if (i.RType.func == OP_DINSM)
324 db_printf("dinsm\t%s,%s,%d,%d",
325 reg_name[i.RType.rt],
326 reg_name[i.RType.rs],
327 i.RType.shamt,
328 i.RType.rd-i.RType.shamt+33);
329 else if (i.RType.func == OP_DINSU)
330 db_printf("dinsu\t%s,%s,%d,%d",
331 reg_name[i.RType.rt],
332 reg_name[i.RType.rs],
333 i.RType.shamt+32,
334 i.RType.rd-i.RType.shamt+1);
335 else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
336 db_printf("wsbh\t%s,%s",
337 reg_name[i.RType.rd],
338 reg_name[i.RType.rt]);
339 else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
340 db_printf("seb\t%s,%s",
341 reg_name[i.RType.rd],
342 reg_name[i.RType.rt]);
343 else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
344 db_printf("seh\t%s,%s",
345 reg_name[i.RType.rd],
346 reg_name[i.RType.rt]);
347 else if (i.RType.func == OP_RDHWR)
348 db_printf("rdhwr\t%s,%s",
349 reg_name[i.RType.rd],
350 reg_name[i.RType.rt]);
351 else
352 db_printf("Unknown");
353 break;
354
355 case OP_BCOND:
356 db_printf("%s\t%s,", bcond_name[i.IType.rt],
357 reg_name[i.IType.rs]);
358 goto pr_displ;
359
360 case OP_BLEZ:
361 case OP_BGTZ:
362 db_printf("%s\t%s,", op_name[i.IType.op],
363 reg_name[i.IType.rs]);
364 goto pr_displ;
365
366 case OP_BEQ:
367 if (i.IType.rs == 0 && i.IType.rt == 0) {
368 db_printf("b\t");
369 goto pr_displ;
370 }
371 /* FALLTHROUGH */
372 case OP_BNE:
373 db_printf("%s\t%s,%s,", op_name[i.IType.op],
374 reg_name[i.IType.rs],
375 reg_name[i.IType.rt]);
376 pr_displ:
377 print_addr(loc + 4 + ((short)i.IType.imm << 2));
378 bdslot = true;
379 break;
380
381 case OP_COP0:
382 switch (i.RType.rs) {
383 case OP_BCx:
384 case OP_BCy:
385
386 db_printf("bc0%c\t",
387 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
388 goto pr_displ;
389
390 case OP_MT:
391 db_printf("mtc0\t%s,%s",
392 reg_name[i.RType.rt],
393 c0_reg[i.RType.rd]);
394 break;
395
396 case OP_DMT:
397 db_printf("dmtc0\t%s,%s",
398 reg_name[i.RType.rt],
399 c0_reg[i.RType.rd]);
400 break;
401
402 case OP_MF:
403 db_printf("mfc0\t%s,%s",
404 reg_name[i.RType.rt],
405 c0_reg[i.RType.rd]);
406 break;
407
408 case OP_DMF:
409 db_printf("dmfc0\t%s,%s",
410 reg_name[i.RType.rt],
411 c0_reg[i.RType.rd]);
412 break;
413
414 default:
415 db_printf("%s", c0_opname[i.FRType.func]);
416 }
417 break;
418
419 case OP_COP1:
420 switch (i.RType.rs) {
421 case OP_BCx:
422 case OP_BCy:
423 db_printf("bc1%c\t",
424 "ft"[i.RType.rt & COPz_BC_TF_MASK]);
425 goto pr_displ;
426
427 case OP_MT:
428 db_printf("mtc1\t%s,f%d",
429 reg_name[i.RType.rt],
430 i.RType.rd);
431 break;
432
433 case OP_MF:
434 db_printf("mfc1\t%s,f%d",
435 reg_name[i.RType.rt],
436 i.RType.rd);
437 break;
438
439 case OP_CT:
440 db_printf("ctc1\t%s,f%d",
441 reg_name[i.RType.rt],
442 i.RType.rd);
443 break;
444
445 case OP_CF:
446 db_printf("cfc1\t%s,f%d",
447 reg_name[i.RType.rt],
448 i.RType.rd);
449 break;
450
451 default:
452 db_printf("%s.%s\tf%d,f%d,f%d",
453 cop1_name[i.FRType.func],
454 fmt_name[i.FRType.fmt],
455 i.FRType.fd, i.FRType.fs, i.FRType.ft);
456 }
457 break;
458
459 case OP_J:
460 case OP_JAL:
461 db_printf("%s\t", op_name[i.JType.op]);
462 print_addr((loc & 0xFFFFFFFFF0000000) | (i.JType.target << 2));
463 bdslot = true;
464 break;
465
466 case OP_LWC1:
467 case OP_SWC1:
468 db_printf("%s\tf%d,", op_name[i.IType.op],
469 i.IType.rt);
470 goto loadstore;
471
472 case OP_LB:
473 case OP_LH:
474 case OP_LW:
475 case OP_LD:
476 case OP_LBU:
477 case OP_LHU:
478 case OP_LWU:
479 case OP_SB:
480 case OP_SH:
481 case OP_SW:
482 case OP_SD:
483 db_printf("%s\t%s,", op_name[i.IType.op],
484 reg_name[i.IType.rt]);
485 loadstore:
486 db_printf("%d(%s)", (short)i.IType.imm,
487 reg_name[i.IType.rs]);
488 break;
489
490 case OP_ORI:
491 case OP_XORI:
492 if (i.IType.rs == 0) {
493 db_printf("li\t%s,0x%x",
494 reg_name[i.IType.rt],
495 i.IType.imm);
496 break;
497 }
498 /* FALLTHROUGH */
499 case OP_ANDI:
500 db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
501 reg_name[i.IType.rt],
502 reg_name[i.IType.rs],
503 i.IType.imm);
504 break;
505
506 case OP_AUI:
507 if (i.IType.rs == 0) {
508 db_printf("lui\t%s,0x%x", reg_name[i.IType.rt],
509 i.IType.imm);
510 } else {
511 db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
512 reg_name[i.IType.rt], reg_name[i.IType.rs],
513 (short)i.IType.imm);
514 }
515 break;
516
517 case OP_ADDIU:
518 case OP_DADDIU:
519 if (i.IType.rs == 0) {
520 db_printf("li\t%s,%d",
521 reg_name[i.IType.rt],
522 (short)i.IType.imm);
523 break;
524 }
525 /* FALLTHROUGH */
526 default:
527 db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
528 reg_name[i.IType.rt],
529 reg_name[i.IType.rs],
530 (short)i.IType.imm);
531 }
532 // db_printf("\n");
533 // if (bdslot) {
534 // db_printf(" bd: ");
535 // mips_disassem(loc+4);
536 // return (loc + 8);
537 // }
538 return (loc + 4);
539}
540
541static void
542print_addr(db_addr_t loc)
543{
544 db_printf("0x%08lx", loc);
545}
546
547static void db_printf(const char* fmt, ...)
548{
549 int cnt;
550 va_list argp;
551 va_start(argp, fmt);
552 if (sprintf_buffer) {
553 cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
554 sprintf_buffer += cnt;
555 sprintf_buf_len -= cnt;
556 } else {
557 vprintf(fmt, argp);
558 }
559}
560
561/*
562 * Disassemble instruction at 'loc'.
563 * Return address of start of next instruction.
564 * Since this function is used by 'examine' and by 'step'
565 * "next instruction" does NOT mean the next instruction to
566 * be executed but the 'linear' next instruction.
567 */
568db_addr_t
569mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
570{
571 u_int32_t instr;
572
573 if (alt_dis_format) { // use ARM register names for disassembly
574 reg_name = &alt_arm_reg_name[0];
575 }
576
577 sprintf_buffer = di_buffer; // quick 'n' dirty printf() vs sprintf()
578 sprintf_buf_len = 39; // should be passed in
579
580 instr = *(u_int32_t *)loc;
581 return (db_disasm_insn(instr, loc, false));
582}
diff --git a/libpixelflinger/codeflinger/mips64_disassem.h b/libpixelflinger/codeflinger/mips64_disassem.h
new file mode 100644
index 000000000..c94f04f9b
--- /dev/null
+++ b/libpixelflinger/codeflinger/mips64_disassem.h
@@ -0,0 +1,56 @@
1/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
35 */
36
37
38
39#ifndef ANDROID_MIPS_DISASSEM_H
40#define ANDROID_MIPS_DISASSEM_H
41
42#include <sys/types.h>
43
44#if __cplusplus
45extern "C" {
46#endif
47
48/* Prototypes for callable functions */
49
50void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt);
51
52#if __cplusplus
53}
54#endif
55
56#endif /* !ANDROID_MIPS_DISASSEM_H */
diff --git a/libpixelflinger/codeflinger/mips_disassem.c b/libpixelflinger/codeflinger/mips_disassem.c
index 4ab9bd35d..3007b1534 100644
--- a/libpixelflinger/codeflinger/mips_disassem.c
+++ b/libpixelflinger/codeflinger/mips_disassem.c
@@ -323,14 +323,14 @@ db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
323 db_printf("ext\t%s,%s,%d,%d", 323 db_printf("ext\t%s,%s,%d,%d",
324 reg_name[i.RType.rt], 324 reg_name[i.RType.rt],
325 reg_name[i.RType.rs], 325 reg_name[i.RType.rs],
326 i.RType.rd+1, 326 i.RType.shamt,
327 i.RType.shamt); 327 i.RType.rd+1);
328 else if (i.RType.func == OP_INS) 328 else if (i.RType.func == OP_INS)
329 db_printf("ins\t%s,%s,%d,%d", 329 db_printf("ins\t%s,%s,%d,%d",
330 reg_name[i.RType.rt], 330 reg_name[i.RType.rt],
331 reg_name[i.RType.rs], 331 reg_name[i.RType.rs],
332 i.RType.rd+1, 332 i.RType.shamt,
333 i.RType.shamt); 333 i.RType.rd-i.RType.shamt+1);
334 else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH) 334 else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
335 db_printf("wsbh\t%s,%s", 335 db_printf("wsbh\t%s,%s",
336 reg_name[i.RType.rd], 336 reg_name[i.RType.rd],
diff --git a/libpixelflinger/codeflinger/mips_opcode.h b/libpixelflinger/codeflinger/mips_opcode.h
index 7ed5ef579..45bb19ea1 100644
--- a/libpixelflinger/codeflinger/mips_opcode.h
+++ b/libpixelflinger/codeflinger/mips_opcode.h
@@ -125,69 +125,118 @@ typedef union {
125#define OP_BLEZ 006 125#define OP_BLEZ 006
126#define OP_BGTZ 007 126#define OP_BGTZ 007
127 127
128#if __mips_isa_rev < 6
128#define OP_ADDI 010 129#define OP_ADDI 010
130#else
131#define OP_POP10 010
132#endif
133
129#define OP_ADDIU 011 134#define OP_ADDIU 011
130#define OP_SLTI 012 135#define OP_SLTI 012
131#define OP_SLTIU 013 136#define OP_SLTIU 013
132#define OP_ANDI 014 137#define OP_ANDI 014
133#define OP_ORI 015 138#define OP_ORI 015
134#define OP_XORI 016 139#define OP_XORI 016
140
141#if __mips_isa_rev < 6
135#define OP_LUI 017 142#define OP_LUI 017
143#else
144#define OP_AUI 017
145#endif
136 146
137#define OP_COP0 020 147#define OP_COP0 020
138#define OP_COP1 021 148#define OP_COP1 021
139#define OP_COP2 022 149#define OP_COP2 022
150
151#if __mips_isa_rev < 6
140#define OP_COP3 023 152#define OP_COP3 023
141#define OP_BEQL 024 /* MIPS-II, for r4000 port */ 153#define OP_BEQL 024
142#define OP_BNEL 025 /* MIPS-II, for r4000 port */ 154#define OP_BNEL 025
143#define OP_BLEZL 026 /* MIPS-II, for r4000 port */ 155#define OP_BLEZL 026
144#define OP_BGTZL 027 /* MIPS-II, for r4000 port */ 156#define OP_BGTZL 027
157#define OP_DADDI 030
158#else
159#define OP_POP26 026
160#define OP_POP27 027
161#define OP_POP30 030
162#endif
145 163
146#define OP_DADDI 030 /* MIPS-II, for r4000 port */ 164#define OP_DADDIU 031
147#define OP_DADDIU 031 /* MIPS-II, for r4000 port */
148#define OP_LDL 032 /* MIPS-II, for r4000 port */
149#define OP_LDR 033 /* MIPS-II, for r4000 port */
150 165
151#define OP_SPECIAL2 034 /* QED opcodes */ 166#if __mips_isa_rev < 6
152#define OP_SPECIAL3 037 /* mips32r2 opcodes */ 167#define OP_LDL 032
168#define OP_LDR 033
169#define OP_SPECIAL2 034
170#else
171#define OP_DAUI 035
172#endif
173
174#define OP_SPECIAL3 037
153 175
154#define OP_LB 040 176#define OP_LB 040
155#define OP_LH 041 177#define OP_LH 041
178
179#if __mips_isa_rev < 6
156#define OP_LWL 042 180#define OP_LWL 042
181#endif
182
157#define OP_LW 043 183#define OP_LW 043
158#define OP_LBU 044 184#define OP_LBU 044
159#define OP_LHU 045 185#define OP_LHU 045
160#define OP_LWR 046 186#define OP_LWR 046
161#define OP_LHU 045 187#define OP_LHU 045
188
189#if __mips_isa_rev < 6
162#define OP_LWR 046 190#define OP_LWR 046
163#define OP_LWU 047 /* MIPS-II, for r4000 port */ 191#endif
192
193#define OP_LWU 047
164 194
165#define OP_SB 050 195#define OP_SB 050
166#define OP_SH 051 196#define OP_SH 051
197
198#if __mips_isa_rev < 6
167#define OP_SWL 052 199#define OP_SWL 052
200#endif
201
168#define OP_SW 053 202#define OP_SW 053
169#define OP_SDL 054 /* MIPS-II, for r4000 port */
170#define OP_SDR 055 /* MIPS-II, for r4000 port */
171#define OP_SWR 056
172#define OP_CACHE 057 /* MIPS-II, for r4000 port */
173 203
204#if __mips_isa_rev < 6
205#define OP_SDL 054
206#define OP_SDR 055
207#define OP_SWR 056
208#define OP_CACHE 057
174#define OP_LL 060 209#define OP_LL 060
175#define OP_LWC0 OP_LL /* backwards source compatibility */ 210#define OP_LWC0 OP_LL
176#define OP_LWC1 061 211#define OP_LWC1 061
177#define OP_LWC2 062 212#define OP_LWC2 062
178#define OP_LWC3 063 213#define OP_LWC3 063
179#define OP_LLD 064 /* MIPS-II, for r4000 port */ 214#define OP_LLD 064
215#else
216#define OP_LWC1 061
217#define OP_BC 062
218#endif
219
180#define OP_LDC1 065 220#define OP_LDC1 065
181#define OP_LD 067 /* MIPS-II, for r4000 port */ 221#define OP_LD 067
182 222
223#if __mips_isa_rev < 6
183#define OP_SC 070 224#define OP_SC 070
184#define OP_SWC0 OP_SC /* backwards source compatibility */ 225#define OP_SWC0 OP_SC
226#endif
227
185#define OP_SWC1 071 228#define OP_SWC1 071
229
230#if __mips_isa_rev < 6
186#define OP_SWC2 072 231#define OP_SWC2 072
187#define OP_SWC3 073 232#define OP_SWC3 073
188#define OP_SCD 074 /* MIPS-II, for r4000 port */ 233#define OP_SCD 074
234#else
235#define OP_BALC 072
236#endif
237
189#define OP_SDC1 075 238#define OP_SDC1 075
190#define OP_SD 077 /* MIPS-II, for r4000 port */ 239#define OP_SD 077
191 240
192/* 241/*
193 * Values for the 'func' field when 'op' == OP_SPECIAL. 242 * Values for the 'func' field when 'op' == OP_SPECIAL.
@@ -199,28 +248,50 @@ typedef union {
199#define OP_SRLV 006 248#define OP_SRLV 006
200#define OP_SRAV 007 249#define OP_SRAV 007
201 250
251#if __mips_isa_rev < 6
202#define OP_JR 010 252#define OP_JR 010
253#endif
254
203#define OP_JALR 011 255#define OP_JALR 011
204#define OP_SYSCALL 014 256#define OP_SYSCALL 014
205#define OP_BREAK 015 257#define OP_BREAK 015
206#define OP_SYNC 017 /* MIPS-II, for r4000 port */ 258#define OP_SYNC 017
207 259
260#if __mips_isa_rev < 6
208#define OP_MFHI 020 261#define OP_MFHI 020
209#define OP_MTHI 021 262#define OP_MTHI 021
210#define OP_MFLO 022 263#define OP_MFLO 022
211#define OP_MTLO 023 264#define OP_MTLO 023
212#define OP_DSLLV 024 /* MIPS-II, for r4000 port */ 265#else
213#define OP_DSRLV 026 /* MIPS-II, for r4000 port */ 266#define OP_CLZ 020
214#define OP_DSRAV 027 /* MIPS-II, for r4000 port */ 267#define OP_CLO 021
268#define OP_DCLZ 022
269#define OP_DCLO 023
270#endif
271
272#define OP_DSLLV 024
273#define OP_DSRLV 026
274#define OP_DSRAV 027
215 275
276#if __mips_isa_rev < 6
216#define OP_MULT 030 277#define OP_MULT 030
217#define OP_MULTU 031 278#define OP_MULTU 031
218#define OP_DIV 032 279#define OP_DIV 032
219#define OP_DIVU 033 280#define OP_DIVU 033
220#define OP_DMULT 034 /* MIPS-II, for r4000 port */ 281#define OP_DMULT 034
221#define OP_DMULTU 035 /* MIPS-II, for r4000 port */ 282#define OP_DMULTU 035
222#define OP_DDIV 036 /* MIPS-II, for r4000 port */ 283#define OP_DDIV 036
223#define OP_DDIVU 037 /* MIPS-II, for r4000 port */ 284#define OP_DDIVU 037
285#else
286#define OP_SOP30 030
287#define OP_SOP31 031
288#define OP_SOP32 032
289#define OP_SOP33 033
290#define OP_SOP34 034
291#define OP_SOP35 035
292#define OP_SOP36 036
293#define OP_SOP37 037
294#endif
224 295
225#define OP_ADD 040 296#define OP_ADD 040
226#define OP_ADDU 041 297#define OP_ADDU 041
@@ -233,73 +304,96 @@ typedef union {
233 304
234#define OP_SLT 052 305#define OP_SLT 052
235#define OP_SLTU 053 306#define OP_SLTU 053
236#define OP_DADD 054 /* MIPS-II, for r4000 port */ 307#define OP_DADD 054
237#define OP_DADDU 055 /* MIPS-II, for r4000 port */ 308#define OP_DADDU 055
238#define OP_DSUB 056 /* MIPS-II, for r4000 port */ 309#define OP_DSUB 056
239#define OP_DSUBU 057 /* MIPS-II, for r4000 port */ 310#define OP_DSUBU 057
240 311
241#define OP_TGE 060 /* MIPS-II, for r4000 port */ 312#define OP_TGE 060
242#define OP_TGEU 061 /* MIPS-II, for r4000 port */ 313#define OP_TGEU 061
243#define OP_TLT 062 /* MIPS-II, for r4000 port */ 314#define OP_TLT 062
244#define OP_TLTU 063 /* MIPS-II, for r4000 port */ 315#define OP_TLTU 063
245#define OP_TEQ 064 /* MIPS-II, for r4000 port */ 316#define OP_TEQ 064
246#define OP_TNE 066 /* MIPS-II, for r4000 port */ 317#define OP_TNE 066
247 318
248#define OP_DSLL 070 /* MIPS-II, for r4000 port */ 319#define OP_DSLL 070
249#define OP_DSRL 072 /* MIPS-II, for r4000 port */ 320#define OP_DSRL 072
250#define OP_DSRA 073 /* MIPS-II, for r4000 port */ 321#define OP_DSRA 073
251#define OP_DSLL32 074 /* MIPS-II, for r4000 port */ 322#define OP_DSLL32 074
252#define OP_DSRL32 076 /* MIPS-II, for r4000 port */ 323#define OP_DSRL32 076
253#define OP_DSRA32 077 /* MIPS-II, for r4000 port */ 324#define OP_DSRA32 077
254 325
326#if __mips_isa_rev < 6
255/* 327/*
256 * Values for the 'func' field when 'op' == OP_SPECIAL2. 328 * Values for the 'func' field when 'op' == OP_SPECIAL2.
329 * OP_SPECIAL2 opcodes are removed in mips32r6
257 */ 330 */
258#define OP_MAD 000 /* QED */ 331#define OP_MAD 000 /* QED */
259#define OP_MADU 001 /* QED */ 332#define OP_MADU 001 /* QED */
260#define OP_MUL 002 /* QED */ 333#define OP_MUL 002 /* QED */
334#endif
261 335
262/* 336/*
263 * Values for the 'func' field when 'op' == OP_SPECIAL3. 337 * Values for the 'func' field when 'op' == OP_SPECIAL3.
264 */ 338 */
265#define OP_EXT 000 339#define OP_EXT 000
340#define OP_DEXTM 001
341#define OP_DEXTU 002
342#define OP_DEXT 003
266#define OP_INS 004 343#define OP_INS 004
344#define OP_DINSM 005
345#define OP_DINSU 006
346#define OP_DINS 007
267#define OP_BSHFL 040 347#define OP_BSHFL 040
348#define OP_RDHWR 073
268 349
269/* 350/*
270 * Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL. 351 * Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL.
271 */ 352 */
353
272#define OP_WSBH 002 354#define OP_WSBH 002
273#define OP_SEB 020 355#define OP_SEB 020
274#define OP_SEH 030 356#define OP_SEH 030
275 357
358#if __mips_isa_rev == 6
359/*
360 * Values for the 'shamt' field when OP_SOP30.
361 */
362#define OP_MUL 002
363#define OP_MUH 003
364#endif
365
276/* 366/*
277 * Values for the 'func' field when 'op' == OP_BCOND. 367 * Values for the 'func' field when 'op' == OP_BCOND.
278 */ 368 */
279#define OP_BLTZ 000 369#define OP_BLTZ 000
280#define OP_BGEZ 001 370#define OP_BGEZ 001
281#define OP_BLTZL 002 /* MIPS-II, for r4000 port */
282#define OP_BGEZL 003 /* MIPS-II, for r4000 port */
283 371
284#define OP_TGEI 010 /* MIPS-II, for r4000 port */ 372#if __mips_isa_rev < 6
285#define OP_TGEIU 011 /* MIPS-II, for r4000 port */ 373#define OP_BLTZL 002
286#define OP_TLTI 012 /* MIPS-II, for r4000 port */ 374#define OP_BGEZL 003
287#define OP_TLTIU 013 /* MIPS-II, for r4000 port */ 375#define OP_TGEI 010
288#define OP_TEQI 014 /* MIPS-II, for r4000 port */ 376#define OP_TGEIU 011
289#define OP_TNEI 016 /* MIPS-II, for r4000 port */ 377#define OP_TLTI 012
290 378#define OP_TLTIU 013
291#define OP_BLTZAL 020 /* MIPS-II, for r4000 port */ 379#define OP_TEQI 014
380#define OP_TNEI 016
381#define OP_BLTZAL 020
292#define OP_BGEZAL 021 382#define OP_BGEZAL 021
293#define OP_BLTZALL 022 383#define OP_BLTZALL 022
294#define OP_BGEZALL 023 384#define OP_BGEZALL 023
385#else
386#define OP_NAL 020
387#define OP_BAL 021
388#endif
295 389
296/* 390/*
297 * Values for the 'rs' field when 'op' == OP_COPz. 391 * Values for the 'rs' field when 'op' == OP_COPz.
298 */ 392 */
299#define OP_MF 000 393#define OP_MF 000
300#define OP_DMF 001 /* MIPS-II, for r4000 port */ 394#define OP_DMF 001
301#define OP_MT 004 395#define OP_MT 004
302#define OP_DMT 005 /* MIPS-II, for r4000 port */ 396#define OP_DMT 005
303#define OP_BCx 010 397#define OP_BCx 010
304#define OP_BCy 014 398#define OP_BCy 014
305#define OP_CF 002 399#define OP_CF 002
@@ -311,6 +405,6 @@ typedef union {
311#define COPz_BC_TF_MASK 0x01 405#define COPz_BC_TF_MASK 0x01
312#define COPz_BC_TRUE 0x01 406#define COPz_BC_TRUE 0x01
313#define COPz_BC_FALSE 0x00 407#define COPz_BC_FALSE 0x00
314#define COPz_BCL_TF_MASK 0x02 /* MIPS-II, for r4000 port */ 408#define COPz_BCL_TF_MASK 0x02
315#define COPz_BCL_TRUE 0x02 /* MIPS-II, for r4000 port */ 409#define COPz_BCL_TRUE 0x02
316#define COPz_BCL_FALSE 0x00 /* MIPS-II, for r4000 port */ 410#define COPz_BCL_FALSE 0x00
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
index d43655cbb..56a6edbea 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_context.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h
@@ -42,7 +42,7 @@ inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
42#else 42#else
43 43
44inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { 44inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
45#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 45#if defined(__mips__) && __mips_isa_rev>=2
46 uint32_t r; 46 uint32_t r;
47 __asm__("wsbh %0, %1;" 47 __asm__("wsbh %0, %1;"
48 "rotr %0, %0, 16" 48 "rotr %0, %0, 16"
@@ -55,7 +55,7 @@ inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) {
55#endif 55#endif
56} 56}
57inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { 57inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) {
58#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 58#if defined(__mips__) && __mips_isa_rev>=2
59 uint32_t r; 59 uint32_t r;
60 __asm__("wsbh %0, %1;" 60 __asm__("wsbh %0, %1;"
61 "rotr %0, %0, 16" 61 "rotr %0, %0, 16"
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
index 787f6202b..17b85dd58 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
@@ -520,6 +520,252 @@ inline int64_t gglMulii(int32_t x, int32_t y)
520 return res; 520 return res;
521} 521}
522 522
523#elif defined(__mips__) && __mips_isa_rev == 6
524
525/*inline MIPS implementations*/
526inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
527inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
528 GGLfixed result,tmp,tmp1,tmp2;
529
530 if (__builtin_constant_p(shift)) {
531 if (shift == 0) {
532 asm ("mul %[res], %[a], %[b] \t\n"
533 : [res]"=&r"(result)
534 : [a]"r"(a),[b]"r"(b)
535 );
536 } else if (shift == 32)
537 {
538 asm ("mul %[res], %[a], %[b] \t\n"
539 "li %[tmp],1\t\n"
540 "sll %[tmp],%[tmp],0x1f\t\n"
541 "addu %[tmp1],%[tmp],%[res] \t\n"
542 "muh %[res], %[a], %[b] \t\n"
543 "sltu %[tmp1],%[tmp1],%[tmp]\t\n" /*obit*/
544 "sra %[tmp],%[tmp],0x1f \t\n"
545 "addu %[res],%[res],%[tmp]\t\n"
546 "addu %[res],%[res],%[tmp1]\t\n"
547 : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
548 : [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
549 );
550 } else if ((shift >0) && (shift < 32))
551 {
552 asm ("mul %[res], %[a], %[b] \t\n"
553 "li %[tmp],1 \t\n"
554 "sll %[tmp],%[tmp],%[shiftm1] \t\n"
555 "addu %[tmp1],%[tmp],%[res] \t\n"
556 "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
557 "addu %[res],%[res],%[tmp] \t\n"
558 "muh %[tmp], %[a], %[b] \t\n"
559 "addu %[tmp],%[tmp],%[tmp1] \t\n"
560 "sll %[tmp],%[tmp],%[lshift] \t\n"
561 "srl %[res],%[res],%[rshift] \t\n"
562 "or %[res],%[res],%[tmp] \t\n"
563 : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
564 : [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
565 );
566 } else {
567 asm ("mul %[res], %[a], %[b] \t\n"
568 "li %[tmp],1 \t\n"
569 "sll %[tmp],%[tmp],%[shiftm1] \t\n"
570 "addu %[tmp1],%[tmp],%[res] \t\n"
571 "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
572 "sra %[tmp2],%[tmp],0x1f \t\n"
573 "addu %[res],%[res],%[tmp] \t\n"
574 "muh %[tmp], %[a], %[b] \t\n"
575 "addu %[tmp],%[tmp],%[tmp2] \t\n"
576 "addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
577 "srl %[tmp2],%[res],%[rshift] \t\n"
578 "srav %[res], %[tmp],%[rshift]\t\n"
579 "sll %[tmp],%[tmp],1 \t\n"
580 "sll %[tmp],%[tmp],%[norbits] \t\n"
581 "or %[tmp],%[tmp],%[tmp2] \t\n"
582 "seleqz %[tmp],%[tmp],%[bit5] \t\n"
583 "selnez %[res],%[res],%[bit5] \t\n"
584 "or %[res],%[res],%[tmp] \t\n"
585 : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
586 : [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
587 );
588 }
589 } else {
590 asm ("mul %[res], %[a], %[b] \t\n"
591 "li %[tmp],1 \t\n"
592 "sll %[tmp],%[tmp],%[shiftm1] \t\n"
593 "addu %[tmp1],%[tmp],%[res] \t\n"
594 "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/
595 "sra %[tmp2],%[tmp],0x1f \t\n"
596 "addu %[res],%[res],%[tmp] \t\n"
597 "muh %[tmp], %[a], %[b] \t\n"
598 "addu %[tmp],%[tmp],%[tmp2] \t\n"
599 "addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/
600 "srl %[tmp2],%[res],%[rshift] \t\n"
601 "srav %[res], %[tmp],%[rshift]\t\n"
602 "sll %[tmp],%[tmp],1 \t\n"
603 "sll %[tmp],%[tmp],%[norbits] \t\n"
604 "or %[tmp],%[tmp],%[tmp2] \t\n"
605 "seleqz %[tmp],%[tmp],%[bit5] \t\n"
606 "selnez %[res],%[res],%[bit5] \t\n"
607 "or %[res],%[res],%[tmp] \t\n"
608 : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
609 : [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
610 );
611 }
612 return result;
613}
614
615inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
616inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
617 GGLfixed result,t,tmp1,tmp2;
618
619 if (__builtin_constant_p(shift)) {
620 if (shift == 0) {
621 asm ("mul %[lo], %[a], %[b] \t\n"
622 "addu %[lo],%[lo],%[c] \t\n"
623 : [lo]"=&r"(result)
624 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
625 );
626 } else if (shift == 32) {
627 asm ("muh %[lo], %[a], %[b] \t\n"
628 "addu %[lo],%[lo],%[c] \t\n"
629 : [lo]"=&r"(result)
630 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
631 );
632 } else if ((shift>0) && (shift<32)) {
633 asm ("mul %[res], %[a], %[b] \t\n"
634 "muh %[t], %[a], %[b] \t\n"
635 "srl %[res],%[res],%[rshift] \t\n"
636 "sll %[t],%[t],%[lshift] \t\n"
637 "or %[res],%[res],%[t] \t\n"
638 "addu %[res],%[res],%[c] \t\n"
639 : [res]"=&r"(result),[t]"=&r"(t)
640 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
641 );
642 } else {
643 asm ("mul %[res], %[a], %[b] \t\n"
644 "muh %[t], %[a], %[b] \t\n"
645 "nor %[tmp1],$zero,%[shift]\t\n"
646 "srl %[res],%[res],%[shift] \t\n"
647 "sll %[tmp2],%[t],1 \t\n"
648 "sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
649 "or %[tmp1],%[tmp2],%[res] \t\n"
650 "srav %[res],%[t],%[shift] \t\n"
651 "andi %[tmp2],%[shift],0x20\t\n"
652 "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
653 "selnez %[res],%[res],%[tmp2]\t\n"
654 "or %[res],%[res],%[tmp1]\t\n"
655 "addu %[res],%[res],%[c] \t\n"
656 : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
657 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
658 );
659 }
660 } else {
661 asm ("mul %[res], %[a], %[b] \t\n"
662 "muh %[t], %[a], %[b] \t\n"
663 "nor %[tmp1],$zero,%[shift]\t\n"
664 "srl %[res],%[res],%[shift] \t\n"
665 "sll %[tmp2],%[t],1 \t\n"
666 "sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
667 "or %[tmp1],%[tmp2],%[res] \t\n"
668 "srav %[res],%[t],%[shift] \t\n"
669 "andi %[tmp2],%[shift],0x20\t\n"
670 "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
671 "selnez %[res],%[res],%[tmp2]\t\n"
672 "or %[res],%[res],%[tmp1]\t\n"
673 "addu %[res],%[res],%[c] \t\n"
674 : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
675 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
676 );
677 }
678 return result;
679}
680
681inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
682inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
683 GGLfixed result,t,tmp1,tmp2;
684
685 if (__builtin_constant_p(shift)) {
686 if (shift == 0) {
687 asm ("mul %[lo], %[a], %[b] \t\n"
688 "subu %[lo],%[lo],%[c] \t\n"
689 : [lo]"=&r"(result)
690 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
691 );
692 } else if (shift == 32) {
693 asm ("muh %[lo], %[a], %[b] \t\n"
694 "subu %[lo],%[lo],%[c] \t\n"
695 : [lo]"=&r"(result)
696 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
697 );
698 } else if ((shift>0) && (shift<32)) {
699 asm ("mul %[res], %[a], %[b] \t\n"
700 "muh %[t], %[a], %[b] \t\n"
701 "srl %[res],%[res],%[rshift] \t\n"
702 "sll %[t],%[t],%[lshift] \t\n"
703 "or %[res],%[res],%[t] \t\n"
704 "subu %[res],%[res],%[c] \t\n"
705 : [res]"=&r"(result),[t]"=&r"(t)
706 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
707 );
708 } else {
709 asm ("mul %[res], %[a], %[b] \t\n"
710 "muh %[t], %[a], %[b] \t\n"
711 "nor %[tmp1],$zero,%[shift]\t\n"
712 "srl %[res],%[res],%[shift] \t\n"
713 "sll %[tmp2],%[t],1 \t\n"
714 "sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
715 "or %[tmp1],%[tmp2],%[res] \t\n"
716 "srav %[res],%[t],%[shift] \t\n"
717 "andi %[tmp2],%[shift],0x20\t\n"
718 "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
719 "selnez %[res],%[res],%[tmp2]\t\n"
720 "or %[res],%[res],%[tmp1]\t\n"
721 "subu %[res],%[res],%[c] \t\n"
722 : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
723 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
724 );
725 }
726 } else {
727 asm ("mul %[res], %[a], %[b] \t\n"
728 "muh %[t], %[a], %[b] \t\n"
729 "nor %[tmp1],$zero,%[shift]\t\n"
730 "srl %[res],%[res],%[shift] \t\n"
731 "sll %[tmp2],%[t],1 \t\n"
732 "sllv %[tmp2],%[tmp2],%[tmp1] \t\n"
733 "or %[tmp1],%[tmp2],%[res] \t\n"
734 "srav %[res],%[t],%[shift] \t\n"
735 "andi %[tmp2],%[shift],0x20\t\n"
736 "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
737 "selnez %[res],%[res],%[tmp2]\t\n"
738 "or %[res],%[res],%[tmp1]\t\n"
739 "subu %[res],%[res],%[c] \t\n"
740 : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
741 : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
742 );
743 }
744 return result;
745}
746
747inline int64_t gglMulii(int32_t x, int32_t y) CONST;
748inline int64_t gglMulii(int32_t x, int32_t y) {
749 union {
750 struct {
751#if defined(__MIPSEL__)
752 int32_t lo;
753 int32_t hi;
754#elif defined(__MIPSEB__)
755 int32_t hi;
756 int32_t lo;
757#endif
758 } s;
759 int64_t res;
760 }u;
761 asm("mul %0, %2, %3 \t\n"
762 "muh %1, %2, %3 \t\n"
763 : "=r"(u.s.lo), "=&r"(u.s.hi)
764 : "%r"(x), "r"(y)
765 );
766 return u.res;
767}
768
523#else // ---------------------------------------------------------------------- 769#else // ----------------------------------------------------------------------
524 770
525inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST; 771inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index 3d145319a..a718b02c6 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -41,6 +41,8 @@
41#include "codeflinger/Arm64Assembler.h" 41#include "codeflinger/Arm64Assembler.h"
42#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 42#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
43#include "codeflinger/MIPSAssembler.h" 43#include "codeflinger/MIPSAssembler.h"
44#elif defined(__mips__) && defined(__LP64__)
45#include "codeflinger/MIPS64Assembler.h"
44#endif 46#endif
45//#include "codeflinger/ARMAssemblerOptimizer.h" 47//#include "codeflinger/ARMAssemblerOptimizer.h"
46 48
@@ -59,7 +61,7 @@
59# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED 61# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED
60#endif 62#endif
61 63
62#if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__) 64#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))) || defined(__aarch64__)
63# define ANDROID_ARM_CODEGEN 1 65# define ANDROID_ARM_CODEGEN 1
64#else 66#else
65# define ANDROID_ARM_CODEGEN 0 67# define ANDROID_ARM_CODEGEN 0
@@ -73,7 +75,7 @@
73 */ 75 */
74#define DEBUG_NEEDS 0 76#define DEBUG_NEEDS 0
75 77
76#if defined( __mips__) && !defined(__LP64__) && __mips_isa_rev < 6 78#if defined( __mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))
77#define ASSEMBLY_SCRATCH_SIZE 4096 79#define ASSEMBLY_SCRATCH_SIZE 4096
78#elif defined(__aarch64__) 80#elif defined(__aarch64__)
79#define ASSEMBLY_SCRATCH_SIZE 8192 81#define ASSEMBLY_SCRATCH_SIZE 8192
@@ -136,6 +138,9 @@ extern "C" void scanline_t32cb16blend_arm64(uint16_t*, uint32_t*, size_t);
136extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct); 138extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct);
137#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 139#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
138extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t); 140extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
141#elif defined(__mips__) && defined(__LP64__)
142extern "C" void scanline_t32cb16blend_mips64(uint16_t*, uint32_t*, size_t);
143extern "C" void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t col, size_t ct);
139#endif 144#endif
140 145
141// ---------------------------------------------------------------------------- 146// ----------------------------------------------------------------------------
@@ -286,7 +291,7 @@ static const needs_filter_t fill16noblend = {
286 291
287#if ANDROID_ARM_CODEGEN 292#if ANDROID_ARM_CODEGEN
288 293
289#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 294#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))
290static CodeCache gCodeCache(32 * 1024); 295static CodeCache gCodeCache(32 * 1024);
291#elif defined(__aarch64__) 296#elif defined(__aarch64__)
292static CodeCache gCodeCache(48 * 1024); 297static CodeCache gCodeCache(48 * 1024);
@@ -406,8 +411,10 @@ static void pick_scanline(context_t* c)
406 //GGLAssembler assembler( 411 //GGLAssembler assembler(
407 // new ARMAssemblerOptimizer(new ARMAssembler(a)) ); 412 // new ARMAssemblerOptimizer(new ARMAssembler(a)) );
408#endif 413#endif
409#if defined(__mips__) 414#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
410 GGLAssembler assembler( new ArmToMipsAssembler(a) ); 415 GGLAssembler assembler( new ArmToMipsAssembler(a) );
416#elif defined(__mips__) && defined(__LP64__)
417 GGLAssembler assembler( new ArmToMips64Assembler(a) );
411#elif defined(__aarch64__) 418#elif defined(__aarch64__)
412 GGLAssembler assembler( new ArmToArm64Assembler(a) ); 419 GGLAssembler assembler( new ArmToArm64Assembler(a) );
413#endif 420#endif
@@ -2103,6 +2110,8 @@ void scanline_col32cb16blend(context_t* c)
2103#endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN 2110#endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN
2104#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__)) 2111#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__))
2105 scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); 2112 scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct);
2113#elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__mips__) && defined(__LP64__)))
2114 scanline_col32cb16blend_mips64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct);
2106#else 2115#else
2107 uint32_t s = GGL_RGBA_TO_HOST(c->packed8888); 2116 uint32_t s = GGL_RGBA_TO_HOST(c->packed8888);
2108 int sA = (s>>24); 2117 int sA = (s>>24);
@@ -2175,7 +2184,8 @@ last_one:
2175 2184
2176void scanline_t32cb16blend(context_t* c) 2185void scanline_t32cb16blend(context_t* c)
2177{ 2186{
2178#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__))) 2187#if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || defined(__aarch64__) || \
2188 (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)))))
2179 int32_t x = c->iterators.xl; 2189 int32_t x = c->iterators.xl;
2180 size_t ct = c->iterators.xr - x; 2190 size_t ct = c->iterators.xr - x;
2181 int32_t y = c->iterators.y; 2191 int32_t y = c->iterators.y;
@@ -2191,8 +2201,10 @@ void scanline_t32cb16blend(context_t* c)
2191 scanline_t32cb16blend_arm(dst, src, ct); 2201 scanline_t32cb16blend_arm(dst, src, ct);
2192#elif defined(__aarch64__) 2202#elif defined(__aarch64__)
2193 scanline_t32cb16blend_arm64(dst, src, ct); 2203 scanline_t32cb16blend_arm64(dst, src, ct);
2194#elif defined(__mips__) 2204#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
2195 scanline_t32cb16blend_mips(dst, src, ct); 2205 scanline_t32cb16blend_mips(dst, src, ct);
2206#elif defined(__mips__) && defined(__LP64__)
2207 scanline_t32cb16blend_mips64(dst, src, ct);
2196#endif 2208#endif
2197#else 2209#else
2198 dst_iterator16 di(c); 2210 dst_iterator16 di(c);
diff --git a/libpixelflinger/tests/arch-mips/Android.mk b/libpixelflinger/tests/arch-mips/Android.mk
new file mode 100644
index 000000000..fe6979ef6
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/Android.mk
@@ -0,0 +1,6 @@
1ifeq ($(TARGET_ARCH),mips)
2include $(all-subdir-makefiles)
3endif
4ifeq ($(TARGET_ARCH),mipsel)
5include $(all-subdir-makefiles)
6endif
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk
new file mode 100644
index 000000000..40f197f3b
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk
@@ -0,0 +1,18 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 col32cb16blend_test.c \
6 ../../../arch-mips/col32cb16blend.S
7
8LOCAL_SHARED_LIBRARIES :=
9
10LOCAL_C_INCLUDES :=
11
12LOCAL_MODULE:= test-pixelflinger-mips-col32cb16blend
13
14LOCAL_MODULE_TAGS := tests
15
16LOCAL_MULTILIB := 32
17
18include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
new file mode 100644
index 000000000..dd0e60fef
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c
@@ -0,0 +1,125 @@
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <inttypes.h>
34
35
36#define ARGB_8888_MAX 0xFFFFFFFF
37#define ARGB_8888_MIN 0x00000000
38#define RGB_565_MAX 0xFFFF
39#define RGB_565_MIN 0x0000
40
41struct test_t
42{
43 char name[256];
44 uint32_t src_color;
45 uint16_t dst_color;
46 size_t count;
47};
48
49struct test_t tests[] =
50{
51 {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
52 {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
53 {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
54 {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
55 {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
56 {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
57 {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
58 {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
59 {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
60 {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
61};
62
63void scanline_col32cb16blend_mips(uint16_t *dst, uint32_t src, size_t count);
64void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
65{
66 uint32_t srcAlpha = (src>>24);
67 uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
68
69 while (count--)
70 {
71 uint16_t d = *dst;
72 int dstR = (d>>11)&0x1f;
73 int dstG = (d>>5)&0x3f;
74 int dstB = (d)&0x1f;
75 int srcR = (src >> ( 3))&0x1F;
76 int srcG = (src >> ( 8+2))&0x3F;
77 int srcB = (src >> (16+3))&0x1F;
78 srcR += (f*dstR)>>8;
79 srcG += (f*dstG)>>8;
80 srcB += (f*dstB)>>8;
81 *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
82 }
83}
84
85void scanline_col32cb16blend_test()
86{
87 uint16_t dst_c[16], dst_asm[16];
88 uint32_t i, j;
89
90 for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
91 {
92 struct test_t test = tests[i];
93
94 printf("Testing - %s:",test.name);
95
96 memset(dst_c, 0, sizeof(dst_c));
97 memset(dst_asm, 0, sizeof(dst_asm));
98
99 for(j = 0; j < test.count; ++j)
100 {
101 dst_c[j] = test.dst_color;
102 dst_asm[j] = test.dst_color;
103 }
104
105
106 scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
107 scanline_col32cb16blend_mips(dst_asm, test.src_color, test.count);
108
109 if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
110 printf("Passed\n");
111 else
112 printf("Failed\n");
113
114 for(j = 0; j < test.count; ++j)
115 {
116 printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
117 }
118 }
119}
120
121int main()
122{
123 scanline_col32cb16blend_test();
124 return 0;
125}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk
new file mode 100644
index 000000000..d0c0ae4dc
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk
@@ -0,0 +1,18 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 t32cb16blend_test.c \
6 ../../../arch-mips/t32cb16blend.S
7
8LOCAL_SHARED_LIBRARIES :=
9
10LOCAL_C_INCLUDES :=
11
12LOCAL_MODULE:= test-pixelflinger-mips-t32cb16blend
13
14LOCAL_MODULE_TAGS := tests
15
16LOCAL_MULTILIB := 32
17
18include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
new file mode 100644
index 000000000..c6d6937c6
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <inttypes.h>
34
35#define ARGB_8888_MAX 0xFFFFFFFF
36#define ARGB_8888_MIN 0x00000000
37#define RGB_565_MAX 0xFFFF
38#define RGB_565_MIN 0x0000
39
40struct test_t
41{
42 char name[256];
43 uint32_t src_color;
44 uint16_t dst_color;
45 size_t count;
46};
47
48struct test_t tests[] =
49{
50 {"Count 0", 0, 0, 0},
51 {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
52 {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
53 {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
54 {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
55 {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
56 {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
57 {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
58 {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
59 {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
60 {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
61
62};
63
64void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t);
65void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count)
66{
67 while (count--)
68 {
69 uint16_t d = *dst;
70 uint32_t s = *src++;
71 int dstR = (d>>11)&0x1f;
72 int dstG = (d>>5)&0x3f;
73 int dstB = (d)&0x1f;
74 int srcR = (s >> ( 3))&0x1F;
75 int srcG = (s >> ( 8+2))&0x3F;
76 int srcB = (s >> (16+3))&0x1F;
77 int srcAlpha = (s>>24) & 0xFF;
78
79
80 int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1));
81 srcR += (f*dstR)>>8;
82 srcG += (f*dstG)>>8;
83 srcB += (f*dstB)>>8;
84 // srcR = srcR > 0x1F? 0x1F: srcR;
85 // srcG = srcG > 0x3F? 0x3F: srcG;
86 // srcB = srcB > 0x1F? 0x1F: srcB;
87 *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
88 }
89}
90
91void scanline_t32cb16blend_test()
92{
93 uint16_t dst_c[16], dst_asm[16];
94 uint32_t src[16];
95 uint32_t i;
96 uint32_t j;
97
98 for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
99 {
100 struct test_t test = tests[i];
101
102 printf("Testing - %s:",test.name);
103
104 memset(dst_c, 0, sizeof(dst_c));
105 memset(dst_asm, 0, sizeof(dst_asm));
106
107 for(j = 0; j < test.count; ++j)
108 {
109 dst_c[j] = test.dst_color;
110 dst_asm[j] = test.dst_color;
111 src[j] = test.src_color;
112 }
113
114 scanline_t32cb16blend_c(dst_c,src,test.count);
115 scanline_t32cb16blend_mips(dst_asm,src,test.count);
116
117
118 if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
119 printf("Passed\n");
120 else
121 printf("Failed\n");
122
123 for(j = 0; j < test.count; ++j)
124 {
125 printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
126 }
127 }
128}
129
130int main()
131{
132 scanline_t32cb16blend_test();
133 return 0;
134}
diff --git a/libpixelflinger/tests/arch-mips64/Android.mk b/libpixelflinger/tests/arch-mips64/Android.mk
new file mode 100644
index 000000000..3b1c64ec2
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/Android.mk
@@ -0,0 +1,3 @@
1ifeq ($(TARGET_ARCH),mips64)
2include $(all-subdir-makefiles)
3endif
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.mk b/libpixelflinger/tests/arch-mips64/assembler/Android.mk
new file mode 100644
index 000000000..469996126
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/assembler/Android.mk
@@ -0,0 +1,21 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 mips64_assembler_test.cpp\
6 asm_mips_test_jacket.S
7
8LOCAL_SHARED_LIBRARIES := \
9 libcutils \
10 libpixelflinger
11
12LOCAL_C_INCLUDES := \
13 $(LOCAL_PATH)/../../..
14
15LOCAL_MODULE:= test-pixelflinger-mips64-assembler-test
16
17LOCAL_MODULE_TAGS := tests
18
19LOCAL_MULTILIB := 64
20
21include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
new file mode 100644
index 000000000..8a7f74202
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S
@@ -0,0 +1,93 @@
1# /*
2# * Copyright (C) 2015 The Android Open Source Project
3# * All rights reserved.
4# *
5# * Redistribution and use in source and binary forms, with or without
6# * modification, are permitted provided that the following conditions
7# * are met:
8# * * Redistributions of source code must retain the above copyright
9# * notice, this list of conditions and the following disclaimer.
10# * * Redistributions in binary form must reproduce the above copyright
11# * notice, this list of conditions and the following disclaimer in
12# * the documentation and/or other materials provided with the
13# * distribution.
14# *
15# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16# * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17# * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18# * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19# * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20# * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22# * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23# * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24# * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25# * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# * SUCH DAMAGE.
27# */
28
29 .text
30 .align 8
31
32 .global asm_mips_test_jacket
33
34 # // Set the register
35 # // Calls the asm function
36 # // Reads the register values to output register
37
38 # // Parameters
39 # // a0 - Function to jump
40 # // a1 - register values array
41 # // a2 - flag values array
42asm_mips_test_jacket:
43 # // Save registers to stack
44 daddiu $sp, $sp, -96
45 sd $s0, 64($sp)
46 sd $s1, 72($sp)
47 sd $s2, 80($sp)
48 sd $ra, 88($sp)
49
50 move $s0, $a0
51 move $s1, $a1
52 move $s2, $a2
53
54 ld $v0, 16($s1)
55 ld $v1, 24($s1)
56 ld $a0, 32($s1)
57 ld $a1, 40($s1)
58 ld $a2, 48($s1)
59 ld $a3, 56($s1)
60 ld $a4, 64($s1)
61 ld $a5, 72($s1)
62 ld $a6, 80($s1)
63 ld $a7, 88($s1)
64 ld $t0, 96($s1)
65 ld $t1, 104($s1)
66 ld $t2, 112($s1)
67 ld $t3, 120($s1)
68
69 jal $s0
70
71 sd $v0, 16($s1)
72 sd $v1, 24($s1)
73 sd $a0, 32($s1)
74 sd $a1, 40($s1)
75 sd $a2, 48($s1)
76 sd $a3, 56($s1)
77 sd $a4, 64($s1)
78 sd $a5, 72($s1)
79 sd $a6, 80($s1)
80 sd $a7, 88($s1)
81 sd $t0, 96($s1)
82 sd $t1, 104($s1)
83 sd $t2, 112($s1)
84 sd $t3, 120($s1)
85
86 ld $s0, 64($sp)
87 ld $s1, 72($sp)
88 ld $s2, 80($sp)
89 ld $ra, 88($sp)
90
91 daddiu $sp, $sp, 96
92
93 j $ra
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
new file mode 100644
index 000000000..2b25223de
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
@@ -0,0 +1,644 @@
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include <errno.h>
34
35#include <sys/mman.h>
36#include <cutils/ashmem.h>
37#include <cutils/atomic.h>
38#include <cutils/log.h>
39
40#define __STDC_FORMAT_MACROS
41#include <inttypes.h>
42
43#include "codeflinger/ARMAssemblerInterface.h"
44#include "codeflinger/MIPS64Assembler.h"
45using namespace android;
46
47#define TESTS_DATAOP_ENABLE 1
48#define TESTS_DATATRANSFER_ENABLE 1
49#define ASSEMBLY_SCRATCH_SIZE 4096
50
51void *instrMem;
52uint32_t instrMemSize = 128 * 1024;
53char dataMem[8192];
54
55typedef void (*asm_function_t)();
56extern "C" void asm_mips_test_jacket(asm_function_t function,
57 int64_t regs[], int32_t flags[]);
58
59#define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1)
60#define MAX_64BIT ((uint64_t)0xFFFFFFFFFFFFFFFF)
61const uint32_t NA = 0;
62const uint32_t NUM_REGS = 32;
63const uint32_t NUM_FLAGS = 16;
64
65enum instr_t
66{
67 INSTR_ADD,
68 INSTR_SUB,
69 INSTR_AND,
70 INSTR_ORR,
71 INSTR_RSB,
72 INSTR_BIC,
73 INSTR_CMP,
74 INSTR_MOV,
75 INSTR_MVN,
76 INSTR_MUL,
77 INSTR_MLA,
78 INSTR_SMULBB,
79 INSTR_SMULBT,
80 INSTR_SMULTB,
81 INSTR_SMULTT,
82 INSTR_SMULWB,
83 INSTR_SMULWT,
84 INSTR_SMLABB,
85 INSTR_UXTB16,
86 INSTR_UBFX,
87 INSTR_ADDR_ADD,
88 INSTR_ADDR_SUB,
89 INSTR_LDR,
90 INSTR_LDRB,
91 INSTR_LDRH,
92 INSTR_ADDR_LDR,
93 INSTR_LDM,
94 INSTR_STR,
95 INSTR_STRB,
96 INSTR_STRH,
97 INSTR_ADDR_STR,
98 INSTR_STM
99};
100
101enum shift_t
102{
103 SHIFT_LSL,
104 SHIFT_LSR,
105 SHIFT_ASR,
106 SHIFT_ROR,
107 SHIFT_NONE
108};
109
110enum offset_t
111{
112 REG_SCALE_OFFSET,
113 REG_OFFSET,
114 IMM8_OFFSET,
115 IMM12_OFFSET,
116 NO_OFFSET
117};
118
119enum cond_t
120{
121 EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV,
122 HS = CS,
123 LO = CC
124};
125
126const char * cc_code[] =
127{
128 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
129 "HI", "LS","GE","LT", "GT", "LE", "AL", "NV"
130};
131
132struct condTest_t
133{
134 int mode;
135 int32_t Rcond1;
136 int32_t Rcond2;
137 uint64_t Rcond1Value;
138 uint64_t Rcond2Value;
139};
140
141
142struct dataOpTest_t
143{
144 uint32_t id;
145 instr_t op;
146 condTest_t preCond;
147 cond_t cond;
148 bool setFlags;
149 uint64_t RnValue;
150 uint64_t RsValue;
151 bool immediate;
152 uint32_t immValue;
153 uint64_t RmValue;
154 uint32_t shiftMode;
155 uint32_t shiftAmount;
156 uint64_t RdValue;
157 bool checkRd;
158 uint64_t postRdValue;
159};
160
161struct dataTransferTest_t
162{
163 uint32_t id;
164 instr_t op;
165 uint32_t preFlag;
166 cond_t cond;
167 bool setMem;
168 uint64_t memOffset;
169 uint64_t memValue;
170 uint64_t RnValue;
171 offset_t offsetType;
172 uint64_t RmValue;
173 uint32_t immValue;
174 bool writeBack;
175 bool preIndex;
176 bool postIndex;
177 uint64_t RdValue;
178 uint64_t postRdValue;
179 uint64_t postRnValue;
180 bool checkMem;
181 uint64_t postMemOffset;
182 uint32_t postMemLength;
183 uint64_t postMemValue;
184};
185
186
187dataOpTest_t dataOpTests [] =
188{
189 {0xA000,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
190 {0xA001,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,MAX_64BIT},
191 {0xA002,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,NA,NA,NA,1,0},
192 {0xA003,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT-1,NA,NA,NA,1,MAX_64BIT},
193 {0xA004,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL, 0,NA,1,0},
194 {0xA005,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
195 {0xA006,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2},
196 {0xA007,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,2},
197 {0xA008,INSTR_ADD,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
198 {0xA009,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
199 {0xA010,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,0,0,0,NA,1,1},
200 {0xA011,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,0,0,0,NA,1,0},
201 {0xA012,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,1},
202 {0xA013,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,0},
203 {0xA014,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,1},
204 {0xA015,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0},
205 {0xA016,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
206 {0xA017,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
207 {0xA018,INSTR_AND,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0},
208 {0xA019,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_ASR,31,NA,1,1},
209 {0xA020,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,1,MAX_32BIT,0,0,0,NA,1,MAX_64BIT},
210 {0xA021,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,1,MAX_32BIT-1,0,0,0,NA,1,MAX_64BIT-1},
211 {0xA022,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,0,0,MAX_32BIT,0,0,NA,1,MAX_64BIT},
212 {0xA023,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,0,0,MAX_32BIT-1,0,0,NA,1,MAX_64BIT-1},
213 {0xA024,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,MAX_64BIT},
214 {0xA025,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001},
215 {0xA026,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
216 {0xA027,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
217 {0xA028,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
218 {0xA029,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,MAX_64BIT},
219 {0xA030,INSTR_CMP,{0,0,0,0,0},AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0},
220 {0xA031,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0},
221 {0xA032,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000},
222 {0xA033,INSTR_MUL,{0,0,0,0,0},AL,0,0,MAX_32BIT,0,0,1,0,0,NA,1,MAX_64BIT},
223 {0xA034,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000},
224 {0xA035,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000},
225 {0xA036,INSTR_SUB,{1,R_v1,R_a6,2,4},MI,0,2,NA,0,NA,1,NA,NA,2,1,1},
226 {0xA037,INSTR_SUB,{2,R_v1,R_a6,2,0},MI,0,2,NA,0,NA,1,NA,NA,2,1,2},
227 {0xA038,INSTR_SUB,{1,R_v1,R_a6,4,2},GE,0,2,NA,1,1,NA,NA,NA,2,1,1},
228 {0xA039,INSTR_SUB,{1,R_a5,R_a6,2,7},GE,0,2,NA,1,1,NA,NA,NA,2,1,2},
229 {0xA040,INSTR_SUB,{1,R_a5,R_a6,1,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,1},
230 {0xA041,INSTR_SUB,{1,R_a5,R_a6,0,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,2},
231 {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))},
232 {0xA043,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_64BIT-1},
233 {0xA044,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1,0,0,0,NA,1,0},
234 {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))},
235 {0xA046,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_64BIT-1},
236 {0xA047,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
237 {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))},
238 {0xA049,INSTR_SUB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT,SHIFT_LSL,31,NA,1,1},
239 {0xA050,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
240 {0xA051,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
241 {0xA052,INSTR_RSB,{1,R_a5,R_a6,4,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,(uint64_t)-2},
242 {0xA053,INSTR_RSB,{1,R_a5,R_a6,-1,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,2},
243 {0xA054,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1<<16,NA,NA,NA,NA,1,(1<<16)-1},
244 {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)},
245 {0xA056,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1,NA,NA,NA,NA,1,0},
246 {0xA057,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(1<<16)-1},
247 {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)},
248 {0xA059,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0},
249 {0xA060,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1<<16)-1},
250 {0xA061,INSTR_RSB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,(uint64_t)(-1)},
251 {0xA062,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0},
252 {0xA063,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0},
253 {0xA064,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0xFFFFFFFF80000001},
254 {0xA065,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0xFFFFFFFF80000001},
255 {0xA066,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,NA,1,MAX_64BIT-1},
256 {0xA067,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000000},
257 {0xA068,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1},
258 {0xA069,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1},
259 {0xA070,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
260 {0xA071,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_64BIT ,SHIFT_ASR,31,NA,1,MAX_64BIT},
261 {0xA072,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0xFFFFFFFF80000001},
262 {0xA073,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3},
263 {0xA074,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,MAX_64BIT -1,SHIFT_ASR,1,NA,1,MAX_64BIT},
264 {0xA075,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1},
265 {0xA076,INSTR_MOV,{2,R_a5,R_a6,6,8},MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
266 {0xA077,INSTR_MOV,{2,R_a5,R_a6,-4,-8},MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
267 {0xA078,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
268 {0xA079,INSTR_MOV,{1,R_a5,R_a6,-1,1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
269 {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},
270 {0xA081,INSTR_MOV,{1,R_a5,R_a6,5,5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
271 {0xA082,INSTR_MOV,{1,R_a5,R_a6,-1,1},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,2},
272 {0xA083,INSTR_MOV,{1,R_a5,R_a6,4,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
273 {0xA084,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
274 {0xA085,INSTR_MOV,{1,R_a5,R_a6,-1,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000},
275 {0xA086,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
276 {0xA087,INSTR_MOV,{1,R_a5,R_a6,-1,-3},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
277 {0xA088,INSTR_MOV,{1,R_a5,R_a6,-1,0},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
278 {0xA089,INSTR_MOV,{1,R_a5,R_a6,-1,-1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
279 {0xA090,INSTR_MOV,{1,R_a5,R_a6,6,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001},
280 {0xA091,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2},
281 {0xA092,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2},
282 {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},
283 {0xA094,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2},
284 {0xA095,INSTR_MOV,{1,R_a5,R_a6,1,-1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2},
285 {0xA096,INSTR_MOV,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001},
286 {0xA097,INSTR_MVN,{1,R_a5,R_a6,1,4},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,2},
287 {0xA098,INSTR_MVN,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,1},
288 {0xA099,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_64BIT},
289 {0xA100,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,MAX_32BIT-1,NA,0,2,1,1},
290 {0xA101,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE},
291 {0xA102,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0},
292 {0xA103,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,1},
293 {0xA104,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,0},
294 {0xA105,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,1},
295 {0xA106,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0},
296 {0xA107,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0},
297 {0xA108,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
298 {0xA109,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
299 {0xA110,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
300 {0xA111,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
301 {0xA112,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
302 {0xA113,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF},
303 {0xA114,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
304 {0xA115,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1},
305 {0xA116,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
306 {0xA117,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
307 {0xA118,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
308 {0xA119,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
309 {0xA120,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
310 {0xA121,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
311 {0xA122,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
312 {0xA123,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1},
313 {0xA124,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
314 {0xA125,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
315 {0xA126,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
316 {0xA127,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
317 {0xA128,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
318 {0xA129,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF},
319 {0xA130,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF},
320 {0xA131,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0},
321 {0xA132,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0},
322 {0xA133,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00001000},
323 {0xA134,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE},
324 {0xA135,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0},
325 {0xA136,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001},
326 {0xA137,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF},
327 {0xA138,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD},
328 {0xA139,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB},
329 {0xA140,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001},
330 {0xA141,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5},
331 {0xA142,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000},
332 {0xA143,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF},
333 {0xA144,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB},
334 {0xA145,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1},
335};
336
337dataTransferTest_t dataTransferTests [] =
338{
339 {0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA},
340 {0xB001,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA},
341 {0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA},
342 {0xB003,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA},
343 {0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA},
344 {0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA},
345 {0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA},
346 {0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA},
347 {0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA},
348 {0xB009,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA},
349 {0xB010,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA},
350 {0xB011,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA},
351 {0xB012,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA},
352 {0xB013,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA},
353 {0xB014,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF},
354 {0xB015,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF},
355 {0xB016,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
356 {0xB017,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF},
357 {0xB018,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF},
358 {0xB019,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF},
359 {0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF},
360 {0xB021,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM8_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF},
361 {0xB022,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF},
362};
363
364
365void flushcache()
366{
367 const long base = long(instrMem);
368 const long curr = base + long(instrMemSize);
369 __builtin___clear_cache((char*)base, (char*)curr);
370}
371
372void dataOpTest(dataOpTest_t test, ArmToMips64Assembler *a64asm, uint32_t Rd = R_v1,
373 uint32_t Rn = R_t0, uint32_t Rm = R_t1, uint32_t Rs = R_t2)
374{
375 int64_t regs[NUM_REGS] = {0};
376 int32_t flags[NUM_FLAGS] = {0};
377 int64_t savedRegs[NUM_REGS] = {0};
378 uint32_t i;
379 uint32_t op2;
380
381 for(i = 0; i < NUM_REGS; ++i)
382 {
383 regs[i] = i;
384 }
385
386 regs[Rd] = test.RdValue;
387 regs[Rn] = test.RnValue;
388 regs[Rs] = test.RsValue;
389 a64asm->reset();
390 if (test.preCond.mode) {
391 a64asm->set_condition(test.preCond.mode, test.preCond.Rcond1, test.preCond.Rcond2);
392 regs[test.preCond.Rcond1] = test.preCond.Rcond1Value;
393 regs[test.preCond.Rcond2] = test.preCond.Rcond2Value;
394 }
395 a64asm->prolog();
396 if(test.immediate == true)
397 {
398 op2 = a64asm->imm(test.immValue);
399 }
400 else if(test.immediate == false && test.shiftAmount == 0)
401 {
402 op2 = Rm;
403 regs[Rm] = (int64_t)((int32_t)(test.RmValue));
404 }
405 else
406 {
407 op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount);
408 regs[Rm] = (int64_t)((int32_t)(test.RmValue));
409 }
410 switch(test.op)
411 {
412 case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
413 case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
414 case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break;
415 case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break;
416 case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break;
417 case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break;
418 case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break;
419 case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break;
420 case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break;
421 case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break;
422 case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break;
423 case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break;
424 case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break;
425 case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break;
426 case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break;
427 case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break;
428 case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break;
429 case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break;
430 case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break;
431 case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break;
432 case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break;
433 default: printf("Error"); return;
434 }
435 a64asm->epilog(0);
436 a64asm->fix_branches();
437 flushcache();
438
439 asm_function_t asm_function = (asm_function_t)(instrMem);
440
441 for(i = 0; i < NUM_REGS; ++i)
442 savedRegs[i] = regs[i];
443
444 asm_mips_test_jacket(asm_function, regs, flags);
445
446 /* Check if all regs except Rd is same */
447 for(i = 0; i < NUM_REGS; ++i)
448 {
449 if((i == Rd) || i == 2) continue;
450 if(regs[i] != savedRegs[i])
451 {
452 printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 "),"
453 "Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i],
454 regs[i]);
455 exit(0);
456 return;
457 }
458 }
459
460 if(test.checkRd == 1 && regs[Rd] != test.postRdValue)
461 {
462 printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n",
463 test.id, test.postRdValue, regs[Rd]);
464 exit(0);
465 }
466 else
467 {
468 printf("Test %x passed\n", test.id);
469 }
470}
471
472
473void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm,
474 uint32_t Rd = R_v1, uint32_t Rn = R_t0,uint32_t Rm = R_t1)
475{
476 int64_t regs[NUM_REGS] = {0};
477 int64_t savedRegs[NUM_REGS] = {0};
478 int32_t flags[NUM_FLAGS] = {0};
479 uint32_t i;
480 for(i = 0; i < NUM_REGS; ++i)
481 {
482 regs[i] = i;
483 }
484
485 uint32_t op2;
486
487 regs[Rd] = test.RdValue;
488 regs[Rn] = (uint64_t)(&dataMem[test.RnValue]);
489 regs[Rm] = test.RmValue;
490 flags[test.preFlag] = 1;
491
492 if(test.setMem == true)
493 {
494 unsigned char *mem = (unsigned char *)&dataMem[test.memOffset];
495 uint64_t value = test.memValue;
496 for(int j = 0; j < 8; ++j)
497 {
498 mem[j] = value & 0x00FF;
499 value >>= 8;
500 }
501 }
502 a64asm->reset();
503 a64asm->prolog();
504 if(test.offsetType == REG_SCALE_OFFSET)
505 {
506 op2 = a64asm->reg_scale_pre(Rm);
507 }
508 else if(test.offsetType == REG_OFFSET)
509 {
510 op2 = a64asm->reg_pre(Rm);
511 }
512 else if(test.offsetType == IMM12_OFFSET && test.preIndex == true)
513 {
514 op2 = a64asm->immed12_pre(test.immValue, test.writeBack);
515 }
516 else if(test.offsetType == IMM12_OFFSET && test.postIndex == true)
517 {
518 op2 = a64asm->immed12_post(test.immValue);
519 }
520 else if(test.offsetType == IMM8_OFFSET && test.preIndex == true)
521 {
522 op2 = a64asm->immed8_pre(test.immValue, test.writeBack);
523 }
524 else if(test.offsetType == IMM8_OFFSET && test.postIndex == true)
525 {
526 op2 = a64asm->immed8_post(test.immValue);
527 }
528 else if(test.offsetType == NO_OFFSET)
529 {
530 op2 = a64asm->__immed12_pre(0);
531 }
532 else
533 {
534 printf("Error - Unknown offset\n"); return;
535 }
536
537 switch(test.op)
538 {
539 case INSTR_LDR: a64asm->LDR(test.cond, Rd,Rn,op2); break;
540 case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break;
541 case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break;
542 case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break;
543 case INSTR_STR: a64asm->STR(test.cond, Rd,Rn,op2); break;
544 case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break;
545 case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break;
546 case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break;
547 default: printf("Error"); return;
548 }
549 a64asm->epilog(0);
550 flushcache();
551
552 asm_function_t asm_function = (asm_function_t)(instrMem);
553
554 for(i = 0; i < NUM_REGS; ++i)
555 savedRegs[i] = regs[i];
556
557 asm_mips_test_jacket(asm_function, regs, flags);
558
559 /* Check if all regs except Rd/Rn are same */
560 for(i = 0; i < NUM_REGS; ++i)
561 {
562 if(i == Rd || i == Rn || i == R_v0) continue;
563
564 if(regs[i] != savedRegs[i])
565 {
566 printf("Test %x failed Reg(%d) tampered"
567 " Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n",
568 test.id, i, savedRegs[i], regs[i]);
569 return;
570 }
571 }
572
573 if((uint64_t)regs[Rd] != test.postRdValue)
574 {
575 printf("Test %x failed, "
576 "Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
577 test.id, test.postRdValue, regs[Rd]);
578 }
579 else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue]))
580 {
581 printf("Test %x failed, "
582 "Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
583 test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem);
584 }
585 else if(test.checkMem == true)
586 {
587 unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset];
588 uint64_t value;
589 value = 0;
590 for(uint32_t j = 0; j < test.postMemLength; ++j)
591 value = (value << 8) | addr[test.postMemLength-j-1];
592 if(value != test.postMemValue)
593 {
594 printf("Test %x failed, "
595 "Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n",
596 test.id, test.postMemValue, value);
597 }
598 else
599 {
600 printf("Test %x passed\n", test.id);
601 }
602 }
603 else
604 {
605 printf("Test %x passed\n", test.id);
606 }
607}
608
609int main(void)
610{
611 uint32_t i;
612
613 /* Allocate memory to store instructions generated by ArmToArm64Assembler */
614 {
615 int fd = ashmem_create_region("code cache", instrMemSize);
616 if(fd < 0) {
617 printf("IF < 0\n");
618 printf("Creating code cache, ashmem_create_region "
619 "failed with error '%s'", strerror(errno));
620 }
621 instrMem = mmap(NULL, instrMemSize,
622 PROT_READ | PROT_WRITE | PROT_EXEC,
623 MAP_PRIVATE, fd, 0);
624 }
625
626 ArmToMips64Assembler a64asm(instrMem);
627
628 if(TESTS_DATAOP_ENABLE)
629 {
630 printf("Running data processing tests\n");
631 for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i) {
632 dataOpTest(dataOpTests[i], &a64asm);
633 }
634 }
635
636 if(TESTS_DATATRANSFER_ENABLE)
637 {
638 printf("Running data transfer tests\n");
639 for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i)
640 dataTransferTest(dataTransferTests[i], &a64asm);
641 }
642
643 return 0;
644}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk
new file mode 100644
index 000000000..7d4177ecb
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk
@@ -0,0 +1,18 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 col32cb16blend_test.c \
6 ../../../arch-mips64/col32cb16blend.S
7
8LOCAL_SHARED_LIBRARIES :=
9
10LOCAL_C_INCLUDES :=
11
12LOCAL_MODULE:= test-pixelflinger-mips64-col32cb16blend
13
14LOCAL_MODULE_TAGS := tests
15
16LOCAL_MULTILIB := 64
17
18include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
new file mode 100644
index 000000000..066eab679
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c
@@ -0,0 +1,125 @@
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <inttypes.h>
34
35
36#define ARGB_8888_MAX 0xFFFFFFFF
37#define ARGB_8888_MIN 0x00000000
38#define RGB_565_MAX 0xFFFF
39#define RGB_565_MIN 0x0000
40
41struct test_t
42{
43 char name[256];
44 uint32_t src_color;
45 uint16_t dst_color;
46 size_t count;
47};
48
49struct test_t tests[] =
50{
51 {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1},
52 {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2},
53 {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3},
54 {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4},
55 {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1},
56 {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2},
57 {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3},
58 {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4},
59 {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5},
60 {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10}
61};
62
63void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t src, size_t count);
64void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count)
65{
66 uint32_t srcAlpha = (src>>24);
67 uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7));
68
69 while (count--)
70 {
71 uint16_t d = *dst;
72 int dstR = (d>>11)&0x1f;
73 int dstG = (d>>5)&0x3f;
74 int dstB = (d)&0x1f;
75 int srcR = (src >> ( 3))&0x1F;
76 int srcG = (src >> ( 8+2))&0x3F;
77 int srcB = (src >> (16+3))&0x1F;
78 srcR += (f*dstR)>>8;
79 srcG += (f*dstG)>>8;
80 srcB += (f*dstB)>>8;
81 *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB);
82 }
83}
84
85void scanline_col32cb16blend_test()
86{
87 uint16_t dst_c[16], dst_asm[16];
88 uint32_t i, j;
89
90 for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i)
91 {
92 struct test_t test = tests[i];
93
94 printf("Testing - %s:",test.name);
95
96 memset(dst_c, 0, sizeof(dst_c));
97 memset(dst_asm, 0, sizeof(dst_asm));
98
99 for(j = 0; j < test.count; ++j)
100 {
101 dst_c[j] = test.dst_color;
102 dst_asm[j] = test.dst_color;
103 }
104
105
106 scanline_col32cb16blend_c(dst_c, test.src_color, test.count);
107 scanline_col32cb16blend_mips64(dst_asm, test.src_color, test.count);
108
109 if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0)
110 printf("Passed\n");
111 else
112 printf("Failed\n");
113
114 for(j = 0; j < test.count; ++j)
115 {
116 printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]);
117 }
118 }
119}
120
121int main()
122{
123 scanline_col32cb16blend_test();
124 return 0;
125}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.mk b/libpixelflinger/tests/arch-mips64/disassembler/Android.mk
new file mode 100644
index 000000000..4e72b5784
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/disassembler/Android.mk
@@ -0,0 +1,16 @@
1LOCAL_PATH:= $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_SRC_FILES:= \
5 mips64_disassembler_test.cpp \
6 ../../../codeflinger/mips64_disassem.c
7
8LOCAL_SHARED_LIBRARIES :=
9
10LOCAL_MODULE:= test-pixelflinger-mips64-disassembler-test
11
12LOCAL_MODULE_TAGS := tests
13
14LOCAL_MULTILIB := 64
15
16include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
new file mode 100644
index 000000000..41f6f3ef9
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp
@@ -0,0 +1,218 @@
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28#include <stdio.h>
29#include <inttypes.h>
30#include <string.h>
31#include "../../../codeflinger/mips64_disassem.h"
32
33//typedef uint64_t db_addr_t;
34//db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_format);
35
36struct test_table_entry_t
37{
38 uint32_t code;
39 const char *instr;
40};
41
42static test_table_entry_t test_table [] =
43{
44 { 0x00011020, "add\tv0,zero,at" },
45 { 0x00832820, "add\ta1,a0,v1" },
46 { 0x00c74020, "add\ta4,a2,a3" },
47 { 0x012a5820, "add\ta7,a5,a6" },
48 { 0x258dffff, "addiu\tt1,t0,-1" },
49 { 0x25cf0004, "addiu\tt3,t2,4" },
50 { 0x02119021, "addu\ts2,s0,s1" },
51 { 0x0274a821, "addu\ts5,s3,s4" },
52 { 0x02d7c024, "and\tt8,s6,s7" },
53 { 0x333aff00, "andi\tk0,t9,0xff00" },
54 { 0x3f7cffff, "aui\tgp,k1,-1" },
55 { 0x3c1dffff, "lui\tsp,0xffff" },
56 { 0x00e04051, "clo\ta4,a3" },
57 { 0x01205050, "clz\ta6,a5" },
58 { 0x016c682c, "dadd\tt1,a7,t0" },
59 { 0x65cf0008, "daddiu\tt3,t2,8" },
60 { 0x0211902d, "daddu\ts2,s0,s1" },
61 { 0x7e741403, "dext\ts4,s3,16,3" },
62 { 0x7eb6f801, "dextm\ts6,s5,0,64" },
63 { 0x7ef87c02, "dextu\tt8,s7,48,16" },
64 { 0x7f3a8207, "dins\tk0,t9,8,9" },
65 { 0x7f7c0005, "dinsm\tgp,k1,0,33" },
66 { 0x7fbe0806, "dinsu\ts8,sp,32,2" },
67 { 0x03e1102e, "dsub\tv0,ra,at" },
68 { 0x0064282f, "dsubu\ta1,v1,a0" },
69 { 0x7cc77a00, "ext\ta3,a2,8,16" },
70 { 0x7d09fc04, "ins\ta5,a4,16,16" },
71 { 0x00200009, "jr\tat" },
72 { 0x00201009, "jalr\tv0,at" },
73 { 0x0020f809, "jalr\tat" },
74 { 0x8082fff0, "lb\tv0,-16(a0)" },
75 { 0x916c0008, "lbu\tt0,8(a7)" },
76 { 0xdfa3ffe8, "ld\tv1,-24(sp)" },
77 { 0x84850080, "lh\ta1,128(a0)" },
78 { 0x94c7ff80, "lhu\ta3,-128(a2)" },
79 { 0x8d09000c, "lw\ta5,12(a4)" },
80 { 0x9d4bfff4, "lwu\ta7,-12(a6)" },
81 { 0x00620898, "mul\tat,v1,v0" },
82 { 0x006208d8, "muh\tat,v1,v0" },
83 { 0x00620899, "mulu\tat,v1,v0" },
84 { 0x006208d9, "muhu\tat,v1,v0" },
85 { 0x00000000, "nop" },
86 { 0x02329827, "nor\ts3,s1,s2" },
87 { 0x0295b025, "or\ts6,s4,s5" },
88 { 0x36f0ff00, "ori\ts0,s7,0xff00" },
89 { 0x7c03103b, "rdhwr\tv0,v1" },
90 { 0x00242a02, "rotr\ta1,a0,8" },
91 { 0x00c74046, "rotrv\ta4,a3,a2" },
92 { 0xa12afff0, "sb\ta6,-16(a5)" },
93 { 0xfd6c0100, "sd\tt0,256(a7)" },
94 { 0x7c0d7420, "seb\tt2,t1" },
95 { 0x7c0f8620, "seh\ts0,t3" },
96 { 0x02329835, "seleqz\ts3,s1,s2" },
97 { 0x0295b037, "selnez\ts6,s4,s5" },
98 { 0xa6f84000, "sh\tt8,16384(s7)" },
99 { 0x0019d100, "sll\tk0,t9,4" },
100 { 0x037ce804, "sllv\tsp,gp,k1" },
101 { 0x03df082a, "slt\tat,s8,ra" },
102 { 0x28430007, "slti\tv1,v0,7" },
103 { 0x2c850020, "sltiu\ta1,a0,32" },
104 { 0x00c7402b, "sltu\ta4,a2,a3" },
105 { 0x00095103, "sra\ta6,a5,4" },
106 { 0x016c6807, "srav\tt1,t0,a7" },
107 { 0x000e7a02, "srl\tt3,t2,8" },
108 { 0x02119006, "srlv\ts2,s1,s0" },
109 { 0x0274a822, "sub\ts5,s3,s4" },
110 { 0x02d7c023, "subu\tt8,s6,s7" },
111 { 0xaf3afffc, "sw\tk0,-4(t9)" },
112 { 0x7c1be0a0, "wsbh\tgp,k1" },
113 { 0x03bef826, "xor\tra,sp,s8" },
114 { 0x3801ffff, "li\tat,0xffff" },
115 { 0x3843ffff, "xori\tv1,v0,0xffff" },
116};
117
118struct test_branches_table_entry_t
119{
120 uint32_t code;
121 const char *instr;
122 int16_t offset;
123};
124
125static test_branches_table_entry_t test_branches_table [] = {
126 { 0x1000ffff, "b\t", 0xffff },
127 { 0x13df0008, "beq\ts8,ra,", 0x8 },
128 { 0x042100ff, "bgez\tat,", 0xff },
129 { 0x1c40ff00, "bgtz\tv0,", 0xff00 },
130 { 0x18605555, "blez\tv1,", 0x5555 },
131 { 0x0480aaaa, "bltz\ta0,", 0xaaaa },
132 { 0x14a68888, "bne\ta1,a2,", 0x8888 },
133};
134
135struct test_jump_table_entry_t
136{
137 uint32_t code;
138 const char *instr;
139 int32_t offset;
140};
141
142static test_jump_table_entry_t test_jump_table [] = {
143 { 0x0956ae66, "j\t", 0x156ae66 },
144 { 0x0d56ae66, "jal\t", 0x156ae66 },
145};
146
147int main()
148{
149 char instr[256];
150 uint32_t failed = 0;
151
152 for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i)
153 {
154 test_table_entry_t *test;
155 test = &test_table[i];
156 mips_disassem(&test->code, instr, 0);
157 if(strcmp(instr, test->instr) != 0)
158 {
159 printf("Test Failed \n"
160 "Code : 0x%0x\n"
161 "Expected : %s\n"
162 "Actual : %s\n", test->code, test->instr, instr);
163 failed++;
164 }
165 }
166 for(uint32_t i = 0; i < sizeof(test_branches_table)/sizeof(test_branches_table_entry_t); ++i)
167 {
168 test_branches_table_entry_t *test;
169 test = &test_branches_table[i];
170 mips_disassem(&test->code, instr, 0);
171 //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
172 uint64_t loc = (uint64_t)test + 4 + (test->offset << 2);
173 //printf("DBG loc: %lx\n", loc);
174 char temp[256], address[16];
175 strcpy(temp, test->instr);
176 sprintf(address, "0x%lx", loc);
177 strcat(temp, address);
178 if(strcmp(instr, temp) != 0)
179 {
180 printf("Test Failed \n"
181 "Code : 0x%0x\n"
182 "Expected : %s\n"
183 "Actual : %s\n", test->code, temp, instr);
184 failed++;
185 }
186 }
187 for(uint32_t i = 0; i < sizeof(test_jump_table)/sizeof(test_jump_table_entry_t); ++i)
188 {
189 test_jump_table_entry_t *test;
190 test = &test_jump_table[i];
191 mips_disassem(&test->code, instr, 0);
192 //printf("DBG code address: %lx\n", (uint64_t)(&test->code));
193 uint64_t loc = ((uint64_t)test & 0xfffffffff0000000) | (test->offset << 2);
194 //printf("DBG loc: %lx\n", loc);
195 char temp[256], address[16];
196 strcpy(temp, test->instr);
197 sprintf(address, "0x%08lx", loc);
198 strcat(temp, address);
199 if(strcmp(instr, temp) != 0)
200 {
201 printf("Test Failed \n"
202 "Code : 0x%0x\n"
203 "Expected : '%s'\n"
204 "Actual : '%s'\n", test->code, temp, instr);
205 failed++;
206 }
207 }
208 if(failed == 0)
209 {
210 printf("All tests PASSED\n");
211 return 0;
212 }
213 else
214 {
215 printf("%d tests FAILED\n", failed);
216 return -1;
217 }
218}
diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp
index 148b6f44d..efa6d87bf 100644
--- a/libpixelflinger/tests/codegen/codegen.cpp
+++ b/libpixelflinger/tests/codegen/codegen.cpp
@@ -11,16 +11,18 @@
11#include "codeflinger/ARMAssembler.h" 11#include "codeflinger/ARMAssembler.h"
12#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 12#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
13#include "codeflinger/MIPSAssembler.h" 13#include "codeflinger/MIPSAssembler.h"
14#elif defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
15#include "codeflinger/MIPS64Assembler.h"
14#endif 16#endif
15#include "codeflinger/Arm64Assembler.h" 17#include "codeflinger/Arm64Assembler.h"
16 18
17#if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__) 19#if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))) || defined(__aarch64__)
18# define ANDROID_ARM_CODEGEN 1 20# define ANDROID_ARM_CODEGEN 1
19#else 21#else
20# define ANDROID_ARM_CODEGEN 0 22# define ANDROID_ARM_CODEGEN 0
21#endif 23#endif
22 24
23#if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 25#if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))
24#define ASSEMBLY_SCRATCH_SIZE 4096 26#define ASSEMBLY_SCRATCH_SIZE 4096
25#elif defined(__aarch64__) 27#elif defined(__aarch64__)
26#define ASSEMBLY_SCRATCH_SIZE 8192 28#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)
58 GGLAssembler assembler( new ArmToMipsAssembler(a) ); 60 GGLAssembler assembler( new ArmToMipsAssembler(a) );
59#endif 61#endif
60 62
63#if defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6
64 GGLAssembler assembler( new ArmToMips64Assembler(a) );
65#endif
66
61#if defined(__aarch64__) 67#if defined(__aarch64__)
62 GGLAssembler assembler( new ArmToArm64Assembler(a) ); 68 GGLAssembler assembler( new ArmToArm64Assembler(a) );
63#endif 69#endif