summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes2015-11-05 12:55:20 -0600
committerLjubomir Papuga2015-11-06 09:02:25 -0600
commit606d4aecfb6a1e911dac207caeba617d1379c1f7 (patch)
treece64e1dee3afd19531fe5e96e446cb2428e94987 /libpixelflinger
parentf8e70a3a60082357885aec58785275bc8a560da3 (diff)
downloadplatform-system-core-606d4aecfb6a1e911dac207caeba617d1379c1f7.tar.gz
platform-system-core-606d4aecfb6a1e911dac207caeba617d1379c1f7.tar.xz
platform-system-core-606d4aecfb6a1e911dac207caeba617d1379c1f7.zip
Revert "Revert "Add MIPS64r6 support for libpixelflinger""
This reverts commit 7fd121788a892a0dfd4a9594304cad85fe366349. Change-Id: Ic1204a8407c235b07c643764d5f2800631fecd72
Diffstat (limited to 'libpixelflinger')
-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 65a3fdfcf..9a937f8f4 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -50,6 +50,14 @@ PIXELFLINGER_SRC_FILES_mips := \
50 arch-mips/t32cb16blend.S \ 50 arch-mips/t32cb16blend.S \
51 51
52endif 52endif
53
54PIXELFLINGER_SRC_FILES_mips64 := \
55 codeflinger/MIPSAssembler.cpp \
56 codeflinger/MIPS64Assembler.cpp \
57 codeflinger/mips64_disassem.c \
58 arch-mips64/col32cb16blend.S \
59 arch-mips64/t32cb16blend.S \
60
53# 61#
54# Shared library 62# Shared library
55# 63#
@@ -59,6 +67,7 @@ LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
59LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) 67LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
60LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) 68LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
61LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) 69LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
70LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64)
62LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) 71LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
63LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include 72LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
64LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) \ 73LOCAL_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..3da291a69
--- /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 "utils/KeyedVector.h"
25#include "utils/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 8fea8cb12..06cb0d0df 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.