diff options
32 files changed, 5035 insertions, 279 deletions
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk index 11e7988b3..87f5a34c3 100644 --- a/libpixelflinger/Android.mk +++ b/libpixelflinger/Android.mk | |||
@@ -52,6 +52,14 @@ PIXELFLINGER_SRC_FILES_mips := \ | |||
52 | arch-mips/t32cb16blend.S \ | 52 | arch-mips/t32cb16blend.S \ |
53 | 53 | ||
54 | endif | 54 | endif |
55 | |||
56 | PIXELFLINGER_SRC_FILES_mips64 := \ | ||
57 | codeflinger/MIPSAssembler.cpp \ | ||
58 | codeflinger/MIPS64Assembler.cpp \ | ||
59 | codeflinger/mips64_disassem.c \ | ||
60 | arch-mips64/col32cb16blend.S \ | ||
61 | arch-mips64/t32cb16blend.S \ | ||
62 | |||
55 | # | 63 | # |
56 | # Shared library | 64 | # Shared library |
57 | # | 65 | # |
@@ -61,6 +69,7 @@ LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES) | |||
61 | LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) | 69 | LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) |
62 | LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) | 70 | LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) |
63 | LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) | 71 | LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) |
72 | LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64) | ||
64 | LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) | 73 | LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) |
65 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | 74 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include |
66 | LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) | 75 | LOCAL_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 | ||
66 | scanline_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 | |||
92 | loop_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 | |||
117 | tail: | ||
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 | |||
124 | loop_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 | |||
132 | done: | ||
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 | */ |
41 | DBG .set noat | 41 | DBG .set noat |
42 | DBG rdhwr $at,$2 | 42 | DBG rdhwr $at,$2 |
43 | DBG .set at | 43 | DBG .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 | ||
75 | DBG .set noat | 82 | DBG .set noat |
76 | DBG rdhwr $t8,$2 | 83 | DBG rdhwr $t8,$2 |
77 | DBG subu $t8,$at | 84 | DBG subu $t8,$at |
78 | DBG sltu $at,$t8,$v0 | 85 | DBG sltu $at,$t8,$v0 |
79 | DBG movn $v0,$t8,$at | 86 | DBG movn $v0,$t8,$at |
80 | DBG sgtu $at,$t8,$v1 | 87 | DBG sgtu $at,$t8,$v1 |
81 | DBG movn $v1,$t8,$at | 88 | DBG movn $v1,$t8,$at |
82 | DBG .set at | 89 | DBG .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 | */ |
92 | DBG .set push | 99 | DBG .set push |
93 | DBG .set noat | 100 | DBG .set noat |
94 | DBG .set mips32r2 | 101 | DBG .set mips32r2 |
95 | DBG rdhwr $at,$2 | 102 | DBG rdhwr $at,$2 |
96 | DBG .set pop | 103 | DBG .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 |
160 | DBG .set push | 167 | DBG .set push |
161 | DBG .set noat | 168 | DBG .set noat |
162 | DBG .set mips32r2 | 169 | DBG .set mips32r2 |
163 | DBG rdhwr $t8,$2 | 170 | DBG rdhwr $t8,$2 |
164 | DBG subu $t8,$at | 171 | DBG subu $t8,$at |
165 | DBG sltu $at,$t8,$v0 | 172 | DBG sltu $at,$t8,$v0 |
166 | DBG movn $v0,$t8,$at | 173 | DBG movn $v0,$t8,$at |
167 | DBG sgtu $at,$t8,$v1 | 174 | DBG sgtu $at,$t8,$v1 |
168 | DBG movn $v1,$t8,$at | 175 | DBG movn $v1,$t8,$at |
169 | DBG .set pop | 176 | DBG .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 |
178 | scanline_t32cb16blend_mips: | 185 | scanline_t32cb16blend_mips: |
179 | DBG li $v0,0xffffffff | 186 | DBG li $v0,0xffffffff |
180 | DBG li $v1,0 | 187 | DBG 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) |
195 | 1: subu $a2,1 | 202 | 1: subu $a2,1 |
196 | 203 | ||
197 | aligned: | 204 | aligned: |
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 */ |
203 | fourpixels: | 210 | fourpixels: |
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 | ||
221 | 1: | 229 | 1: |
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 | ||
237 | 1: subu $a2,4 | 246 | 1: subu $a2,4 |
238 | bgtz $a2,fourpixels | 247 | bgtz $a2,fourpixels |
239 | 248 | ||
240 | tail: | 249 | tail: |
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 |
246 | onepixel: | 255 | onepixel: |
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) |
254 | 1: subu $a2,1 | 263 | 1: subu $a2,1 |
255 | bnez $a2,onepixel | 264 | bnez $a2,onepixel |
256 | done: | 265 | done: |
257 | DBG .set push | 266 | DBG .set push |
258 | DBG .set mips32r2 | 267 | DBG .set mips32r2 |
259 | DBG rdhwr $a0,$3 | 268 | DBG rdhwr $a0,$3 |
260 | DBG mul $v0,$a0 | 269 | DBG mul $v0,$a0 |
261 | DBG mul $v1,$a0 | 270 | DBG mul $v1,$a0 |
262 | DBG .set pop | 271 | DBG .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 | ||
60 | scanline_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 | |||
77 | loop_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 | |||
91 | tail: | ||
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 | |||
98 | loop_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 | |||
106 | done: | ||
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 | ||
82 | scanline_t32cb16blend_mips64: | ||
83 | daddiu $sp, $sp, -40 | ||
84 | DBG li $v0,0xffffffff | ||
85 | DBG 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) | ||
100 | 1: subu $a2,1 | ||
101 | |||
102 | aligned: | ||
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 */ | ||
108 | fourpixels: | ||
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 | |||
127 | 1: | ||
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 | |||
144 | 1: subu $a2,4 | ||
145 | bgtz $a2,fourpixels | ||
146 | |||
147 | tail: | ||
148 | /* the pixel count underran, restore it now */ | ||
149 | addu $a2,4 | ||
150 | |||
151 | /* handle the last 0..3 pixels */ | ||
152 | beqz $a2,done | ||
153 | onepixel: | ||
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) | ||
161 | 1: subu $a2,1 | ||
162 | bnez $a2,onepixel | ||
163 | done: | ||
164 | DBG .set push | ||
165 | DBG .set mips32r2 | ||
166 | DBG rdhwr $a0,$3 | ||
167 | DBG mul $v0,$a0 | ||
168 | DBG mul $v1,$a0 | ||
169 | DBG .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() | |||
1057 | RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch) | 1058 | RegisterAllocator::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) | |||
1067 | RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch) | 1069 | RegisterAllocator::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 | |||
52 | namespace android { | ||
53 | |||
54 | // ---------------------------------------------------------------------------- | ||
55 | #if 0 | ||
56 | #pragma mark - | ||
57 | #pragma mark ArmToMips64Assembler... | ||
58 | #endif | ||
59 | |||
60 | ArmToMips64Assembler::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 | |||
74 | ArmToMips64Assembler::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 | |||
85 | ArmToMips64Assembler::~ArmToMips64Assembler() | ||
86 | { | ||
87 | delete mMips; | ||
88 | free((void *) mArmPC); | ||
89 | } | ||
90 | |||
91 | uint32_t* ArmToMips64Assembler::pc() const | ||
92 | { | ||
93 | return mMips->pc(); | ||
94 | } | ||
95 | |||
96 | uint32_t* ArmToMips64Assembler::base() const | ||
97 | { | ||
98 | return mMips->base(); | ||
99 | } | ||
100 | |||
101 | void ArmToMips64Assembler::reset() | ||
102 | { | ||
103 | cond.labelnum = 0; | ||
104 | mInum = 0; | ||
105 | mMips->reset(); | ||
106 | } | ||
107 | |||
108 | int ArmToMips64Assembler::getCodegenArch() | ||
109 | { | ||
110 | return CODEGEN_ARCH_MIPS64; | ||
111 | } | ||
112 | |||
113 | void ArmToMips64Assembler::comment(const char* string) | ||
114 | { | ||
115 | mMips->comment(string); | ||
116 | } | ||
117 | |||
118 | void ArmToMips64Assembler::label(const char* theLabel) | ||
119 | { | ||
120 | mMips->label(theLabel); | ||
121 | } | ||
122 | |||
123 | void ArmToMips64Assembler::disassemble(const char* name) | ||
124 | { | ||
125 | mMips->disassemble(name); | ||
126 | } | ||
127 | |||
128 | void 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 | |||
143 | void 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 | |||
156 | void 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 | |||
170 | int ArmToMips64Assembler::generate(const char* name) | ||
171 | { | ||
172 | return mMips->generate(name); | ||
173 | } | ||
174 | |||
175 | void ArmToMips64Assembler::fix_branches() | ||
176 | { | ||
177 | mMips->fix_branches(); | ||
178 | } | ||
179 | |||
180 | uint32_t* ArmToMips64Assembler::pcForLabel(const char* label) | ||
181 | { | ||
182 | return mMips->pcForLabel(label); | ||
183 | } | ||
184 | |||
185 | void 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) | ||
204 | int 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 | |||
215 | bool ArmToMips64Assembler::isValidImmediate(uint32_t immediate) | ||
216 | { | ||
217 | // for MIPS, any 32-bit immediate is OK | ||
218 | return true; | ||
219 | } | ||
220 | |||
221 | uint32_t ArmToMips64Assembler::imm(uint32_t immediate) | ||
222 | { | ||
223 | amode.value = immediate; | ||
224 | return AMODE_IMM; | ||
225 | } | ||
226 | |||
227 | uint32_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 | |||
235 | uint32_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 | |||
241 | uint32_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) | ||
250 | uint32_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 | |||
260 | uint32_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 | |||
270 | uint32_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 | |||
282 | uint32_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) | ||
289 | uint32_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 | |||
299 | uint32_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 | |||
308 | uint32_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 | |||
315 | uint32_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 | |||
331 | static 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 | |||
344 | void 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 | ||
366 | int 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 | |||
401 | void 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 | ||
604 | void 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 | |||
618 | void 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 | |||
628 | void 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 | |||
641 | void 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 | |||
657 | void 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 | } | ||
672 | void 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 | |||
697 | void 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 | |||
727 | void 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 .... | ||
734 | void 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 | |||
740 | void 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 | |||
746 | void 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... | ||
760 | void 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 | |||
794 | void 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 | |||
823 | void 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 | |||
859 | void 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 | |||
887 | void 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 | |||
915 | void ArmToMips64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset) | ||
916 | { | ||
917 | mArmPC[mInum++] = pc(); | ||
918 | mMips->NOP2(); | ||
919 | NOT_IMPLEMENTED(); | ||
920 | } | ||
921 | |||
922 | void ArmToMips64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset) | ||
923 | { | ||
924 | mArmPC[mInum++] = pc(); | ||
925 | mMips->NOP2(); | ||
926 | NOT_IMPLEMENTED(); | ||
927 | } | ||
928 | |||
929 | void 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... | ||
965 | void 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 | |||
977 | void 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... | ||
997 | void 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 | |||
1004 | void 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 | |||
1011 | void 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... | ||
1025 | void 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 | |||
1034 | void ArmToMips64Assembler::CLZ(int cc, int Rd, int Rm) | ||
1035 | { | ||
1036 | mArmPC[mInum++] = pc(); | ||
1037 | mMips->CLZ(Rd, Rm); | ||
1038 | } | ||
1039 | |||
1040 | void 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 | |||
1048 | void 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 | |||
1056 | void 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 | |||
1064 | void 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) | ||
1073 | void 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 | ||
1102 | void 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 | ||
1121 | void 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 | |||
1151 | void 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 | |||
1160 | void 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 | ||
1170 | void 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 | |||
1183 | void 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 | |||
1196 | void 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 | |||
1204 | void 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 | |||
1212 | void 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 | |||
1245 | void 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 | |||
1299 | MIPS64Assembler::MIPS64Assembler(const sp<Assembly>& assembly, ArmToMips64Assembler *parent) | ||
1300 | : mParent(parent), | ||
1301 | MIPSAssembler::MIPSAssembler(assembly, NULL) | ||
1302 | { | ||
1303 | } | ||
1304 | |||
1305 | MIPS64Assembler::MIPS64Assembler(void* assembly, ArmToMips64Assembler *parent) | ||
1306 | : mParent(parent), | ||
1307 | MIPSAssembler::MIPSAssembler(NULL, NULL) | ||
1308 | { | ||
1309 | mBase = mPC = (uint32_t *)assembly; | ||
1310 | } | ||
1311 | |||
1312 | MIPS64Assembler::~MIPS64Assembler() | ||
1313 | { | ||
1314 | } | ||
1315 | |||
1316 | void 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 | |||
1330 | void 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 | |||
1370 | void 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 | |||
1384 | void 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 | |||
1390 | void 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 | |||
1395 | void 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 | |||
1401 | void 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 | |||
1406 | void 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 | |||
1412 | void 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 | |||
1418 | void 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 | |||
1424 | void 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 | |||
1430 | void 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 | |||
1435 | void 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 | |||
1440 | void MIPS64Assembler::LUI(int Rt, int16_t offset) | ||
1441 | { | ||
1442 | *mPC++ = (aui_op<<OP_SHF) | (Rt<<RT_SHF) | (offset & MSK_16); | ||
1443 | } | ||
1444 | |||
1445 | |||
1446 | void MIPS64Assembler::JR(int Rs) | ||
1447 | { | ||
1448 | *mPC++ = (spec_op<<OP_SHF) | (Rs<<RS_SHF) | (jalr_fn << FUNC_SHF); | ||
1449 | MIPS64Assembler::NOP(); | ||
1450 | } | ||
1451 | |||
1452 | }; // namespace android: | ||
diff --git a/libpixelflinger/codeflinger/MIPS64Assembler.h b/libpixelflinger/codeflinger/MIPS64Assembler.h new file mode 100644 index 000000000..6c760f4ab --- /dev/null +++ b/libpixelflinger/codeflinger/MIPS64Assembler.h | |||
@@ -0,0 +1,429 @@ | |||
1 | /* libs/pixelflinger/codeflinger/MIPS64Assembler.h | ||
2 | ** | ||
3 | ** Copyright 2015, The Android Open Source Project | ||
4 | ** | ||
5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | ** you may not use this file except in compliance with the License. | ||
7 | ** You may obtain a copy of the License at | ||
8 | ** | ||
9 | ** http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | ** | ||
11 | ** Unless required by applicable law or agreed to in writing, software | ||
12 | ** distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | ** See the License for the specific language governing permissions and | ||
15 | ** limitations under the License. | ||
16 | */ | ||
17 | |||
18 | #ifndef ANDROID_MIPS64ASSEMBLER_H | ||
19 | #define ANDROID_MIPS64ASSEMBLER_H | ||
20 | |||
21 | #include <stdint.h> | ||
22 | #include <sys/types.h> | ||
23 | |||
24 | #include "tinyutils/KeyedVector.h" | ||
25 | #include "tinyutils/Vector.h" | ||
26 | #include "tinyutils/smartpointer.h" | ||
27 | |||
28 | #include "ARMAssemblerInterface.h" | ||
29 | #include "MIPSAssembler.h" | ||
30 | #include "CodeCache.h" | ||
31 | |||
32 | namespace android { | ||
33 | |||
34 | class 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 | ||
39 | class ArmToMips64Assembler : public ARMAssemblerInterface | ||
40 | { | ||
41 | public: | ||
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 | |||
185 | private: | ||
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 | |||
252 | class MIPS64Assembler : public MIPSAssembler | ||
253 | { | ||
254 | public: | ||
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 | |||
305 | protected: | ||
306 | // void string_detab(char *s); | ||
307 | // void string_pad(char *s, int padded_len); | ||
308 | |||
309 | ArmToMips64Assembler *mParent; | ||
310 | sp<Assembly> mAssembly; | ||
311 | uint32_t* mBase; | ||
312 | uint32_t* mPC; | ||
313 | uint32_t* mPrologPC; | ||
314 | int64_t mDuration; | ||
315 | #if defined(WITH_LIB_HARDWARE) | ||
316 | bool mQemuTracing; | ||
317 | #endif | ||
318 | |||
319 | struct branch_target_t { | ||
320 | inline branch_target_t() : label(0), pc(0) { } | ||
321 | inline branch_target_t(const char* l, uint32_t* p) | ||
322 | : label(l), pc(p) { } | ||
323 | const char* label; | ||
324 | uint32_t* pc; | ||
325 | }; | ||
326 | |||
327 | Vector<branch_target_t> mBranchTargets; | ||
328 | KeyedVector< const char*, uint32_t* > mLabels; | ||
329 | KeyedVector< uint32_t*, const char* > mLabelsInverseMapping; | ||
330 | KeyedVector< uint32_t*, const char* > mComments; | ||
331 | |||
332 | |||
333 | // opcode field of all instructions | ||
334 | enum opcode_field { | ||
335 | spec_op, regimm_op, j_op, jal_op, // 0x00 - 0x03 | ||
336 | beq_op, bne_op, pop06_op, pop07_op, // 0x04 - 0x07 | ||
337 | pop10_op, addiu_op, slti_op, sltiu_op, // 0x08 - 0x0b | ||
338 | andi_op, ori_op, xori_op, aui_op, // 0x0c - 0x0f | ||
339 | cop0_op, cop1_op, cop2_op, rsrv_opc_0, // 0x10 - 0x13 | ||
340 | rsrv_opc_1, rsrv_opc_2, pop26_op, pop27_op, // 0x14 - 0x17 | ||
341 | pop30_op, daddiu_op, rsrv_opc_3, rsrv_opc_4, // 0x18 - 0x1b | ||
342 | rsrv_opc_5, daui_op, msa_op, spec3_op, // 0x1c - 0x1f | ||
343 | lb_op, lh_op, rsrv_opc_6, lw_op, // 0x20 - 0x23 | ||
344 | lbu_op, lhu_op, rsrv_opc_7, lwu_op, // 0x24 - 0x27 | ||
345 | sb_op, sh_op, rsrv_opc_8, sw_op, // 0x28 - 0x2b | ||
346 | rsrv_opc_9, rsrv_opc_10, rsrv_opc_11, rsrv_opc_12, // 0x2c - 0x2f | ||
347 | rsrv_opc_13, lwc1_op, bc_op, rsrv_opc_14, // 0x2c - 0x2f | ||
348 | rsrv_opc_15, ldc1_op, pop66_op, ld_op, // 0x30 - 0x33 | ||
349 | rsrv_opc_16, swc1_op, balc_op, pcrel_op, // 0x34 - 0x37 | ||
350 | rsrv_opc_17, sdc1_op, pop76_op, sd_op // 0x38 - 0x3b | ||
351 | }; | ||
352 | |||
353 | |||
354 | // func field for special opcode | ||
355 | enum func_spec_op { | ||
356 | sll_fn, rsrv_spec_0, srl_fn, sra_fn, | ||
357 | sllv_fn, lsa_fn, srlv_fn, srav_fn, | ||
358 | rsrv_spec_1, jalr_fn, rsrv_spec_2, rsrv_spec_3, | ||
359 | syscall_fn, break_fn, sdbbp_fn, sync_fn, | ||
360 | clz_fn, clo_fn, dclz_fn, dclo_fn, | ||
361 | dsllv_fn, dlsa_fn, dsrlv_fn, dsrav_fn, | ||
362 | sop30_fn, sop31_fn, sop32_fn, sop33_fn, | ||
363 | sop34_fn, sop35_fn, sop36_fn, sop37_fn, | ||
364 | add_fn, addu_fn, sub_fn, subu_fn, | ||
365 | and_fn, or_fn, xor_fn, nor_fn, | ||
366 | rsrv_spec_4, rsrv_spec_5, slt_fn, sltu_fn, | ||
367 | dadd_fn, daddu_fn, dsub_fn, dsubu_fn, | ||
368 | tge_fn, tgeu_fn, tlt_fn, tltu_fn, | ||
369 | teq_fn, seleqz_fn, tne_fn, selnez_fn, | ||
370 | dsll_fn, rsrv_spec_6, dsrl_fn, dsra_fn, | ||
371 | dsll32_fn, rsrv_spec_7, dsrl32_fn, dsra32_fn | ||
372 | }; | ||
373 | |||
374 | // func field for spec3 opcode | ||
375 | enum func_spec3_op { | ||
376 | ext_fn, dextm_fn, dextu_fn, dext_fn, | ||
377 | ins_fn, dinsm_fn, dinsu_fn, dins_fn, | ||
378 | cachee_fn = 0x1b, sbe_fn, she_fn, sce_fn, swe_fn, | ||
379 | bshfl_fn, prefe_fn = 0x23, dbshfl_fn, cache_fn, sc_fn, scd_fn, | ||
380 | lbue_fn, lhue_fn, lbe_fn = 0x2c, lhe_fn, lle_fn, lwe_fn, | ||
381 | pref_fn = 0x35, ll_fn, lld_fn, rdhwr_fn = 0x3b | ||
382 | }; | ||
383 | |||
384 | // sa field for spec3 opcodes, with BSHFL function | ||
385 | enum func_spec3_bshfl { | ||
386 | bitswap_fn, | ||
387 | wsbh_fn = 0x02, | ||
388 | dshd_fn = 0x05, | ||
389 | seb_fn = 0x10, | ||
390 | seh_fn = 0x18 | ||
391 | }; | ||
392 | |||
393 | // rt field of regimm opcodes. | ||
394 | enum regimm_fn { | ||
395 | bltz_fn, bgez_fn, | ||
396 | dahi_fn = 0x6, | ||
397 | nal_fn = 0x10, bal_fn, bltzall_fn, bgezall_fn, | ||
398 | sigrie_fn = 0x17, | ||
399 | dati_fn = 0x1e, synci_fn | ||
400 | }; | ||
401 | |||
402 | enum muldiv_fn { | ||
403 | mul_fn = 0x02, muh_fn | ||
404 | }; | ||
405 | |||
406 | enum mips_inst_shifts { | ||
407 | OP_SHF = 26, | ||
408 | JTARGET_SHF = 0, | ||
409 | RS_SHF = 21, | ||
410 | RT_SHF = 16, | ||
411 | RD_SHF = 11, | ||
412 | RE_SHF = 6, | ||
413 | SA_SHF = RE_SHF, // synonym | ||
414 | IMM_SHF = 0, | ||
415 | FUNC_SHF = 0, | ||
416 | |||
417 | // mask values | ||
418 | MSK_16 = 0xffff, | ||
419 | |||
420 | |||
421 | CACHEOP_SHF = 18, | ||
422 | CACHESEL_SHF = 16, | ||
423 | }; | ||
424 | }; | ||
425 | |||
426 | |||
427 | }; // namespace android | ||
428 | |||
429 | #endif //ANDROID_MIPS64ASSEMBLER_H | ||
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp index a88d2fe00..daa231fe0 100644 --- a/libpixelflinger/codeflinger/MIPSAssembler.cpp +++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp | |||
@@ -1358,7 +1358,7 @@ void MIPSAssembler::disassemble(const char* name) | |||
1358 | ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); | 1358 | ::mips_disassem(mipsPC, di_buf, arm_disasm_fmt); |
1359 | string_detab(di_buf); | 1359 | string_detab(di_buf); |
1360 | string_pad(di_buf, 30); | 1360 | string_pad(di_buf, 30); |
1361 | ALOGW("%08x: %08x %s", uint32_t(mipsPC), uint32_t(*mipsPC), di_buf); | 1361 | ALOGW("%08x: %08x %s", uintptr_t(mipsPC), uint32_t(*mipsPC), di_buf); |
1362 | mipsPC++; | 1362 | mipsPC++; |
1363 | } | 1363 | } |
1364 | } | 1364 | } |
@@ -1407,7 +1407,7 @@ int MIPSAssembler::generate(const char* name) | |||
1407 | 1407 | ||
1408 | #if defined(WITH_LIB_HARDWARE) | 1408 | #if defined(WITH_LIB_HARDWARE) |
1409 | if (__builtin_expect(mQemuTracing, 0)) { | 1409 | if (__builtin_expect(mQemuTracing, 0)) { |
1410 | int err = qemu_add_mapping(int(base()), name); | 1410 | int err = qemu_add_mapping(uintptr_t(base()), name); |
1411 | mQemuTracing = (err >= 0); | 1411 | mQemuTracing = (err >= 0); |
1412 | } | 1412 | } |
1413 | #endif | 1413 | #endif |
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h index 430ab064c..68a2b4fe2 100644 --- a/libpixelflinger/codeflinger/MIPSAssembler.h +++ b/libpixelflinger/codeflinger/MIPSAssembler.h | |||
@@ -244,20 +244,20 @@ public: | |||
244 | MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent); | 244 | MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent); |
245 | virtual ~MIPSAssembler(); | 245 | virtual ~MIPSAssembler(); |
246 | 246 | ||
247 | uint32_t* base() const; | 247 | virtual uint32_t* base() const; |
248 | uint32_t* pc() const; | 248 | virtual uint32_t* pc() const; |
249 | void reset(); | 249 | virtual void reset(); |
250 | 250 | ||
251 | void disassemble(const char* name); | 251 | virtual void disassemble(const char* name); |
252 | 252 | ||
253 | void prolog(); | 253 | virtual void prolog(); |
254 | void epilog(uint32_t touched); | 254 | virtual void epilog(uint32_t touched); |
255 | int generate(const char* name); | 255 | virtual int generate(const char* name); |
256 | void comment(const char* string); | 256 | virtual void comment(const char* string); |
257 | void label(const char* string); | 257 | virtual void label(const char* string); |
258 | 258 | ||
259 | // valid only after generate() has been called | 259 | // valid only after generate() has been called |
260 | uint32_t* pcForLabel(const char* label); | 260 | virtual uint32_t* pcForLabel(const char* label); |
261 | 261 | ||
262 | 262 | ||
263 | // ------------------------------------------------------------------------ | 263 | // ------------------------------------------------------------------------ |
@@ -399,9 +399,9 @@ public: | |||
399 | 399 | ||
400 | 400 | ||
401 | 401 | ||
402 | private: | 402 | protected: |
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: | |||
537 | enum mips_regnames { | 537 | enum 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 | |||
48 | static char *sprintf_buffer; | ||
49 | static int sprintf_buf_len; | ||
50 | |||
51 | |||
52 | typedef uint64_t db_addr_t; | ||
53 | static void db_printf(const char* fmt, ...); | ||
54 | |||
55 | static 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 | |||
66 | static 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 | |||
77 | static const char * const bcond_name[32] = { | ||
78 | /* 0 */ "bltz", "bgez", "?", "?", "?", "?", "dahi", "?", | ||
79 | /* 8 */ "?", "?", "?", "?", "?", "?", "?", "?", | ||
80 | /*16 */ "nal", "bal", "?", "?", "?", "?", "?", "sigrie", | ||
81 | /*24 */ "?", "?", "?", "?", "?", "?", "dati", "synci", | ||
82 | }; | ||
83 | |||
84 | static 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 | |||
97 | static 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 | |||
104 | static 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 | |||
111 | static 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 | |||
118 | static char ** reg_name = &mips_reg_name[0]; | ||
119 | |||
120 | static 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 | |||
131 | static 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 | |||
142 | static void print_addr(db_addr_t); | ||
143 | db_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 | */ | ||
150 | static db_addr_t | ||
151 | db_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 | |||
541 | static void | ||
542 | print_addr(db_addr_t loc) | ||
543 | { | ||
544 | db_printf("0x%08lx", loc); | ||
545 | } | ||
546 | |||
547 | static 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 | */ | ||
568 | db_addr_t | ||
569 | mips_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 | ||
45 | extern "C" { | ||
46 | #endif | ||
47 | |||
48 | /* Prototypes for callable functions */ | ||
49 | |||
50 | void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt); | ||
51 | |||
52 | #if __cplusplus | ||
53 | } | ||
54 | #endif | ||
55 | |||
56 | #endif /* !ANDROID_MIPS_DISASSEM_H */ | ||
diff --git a/libpixelflinger/codeflinger/mips_disassem.c b/libpixelflinger/codeflinger/mips_disassem.c index 4ab9bd35d..3007b1534 100644 --- a/libpixelflinger/codeflinger/mips_disassem.c +++ b/libpixelflinger/codeflinger/mips_disassem.c | |||
@@ -323,14 +323,14 @@ db_disasm_insn(int insn, db_addr_t loc, bool altfmt) | |||
323 | db_printf("ext\t%s,%s,%d,%d", | 323 | db_printf("ext\t%s,%s,%d,%d", |
324 | reg_name[i.RType.rt], | 324 | reg_name[i.RType.rt], |
325 | reg_name[i.RType.rs], | 325 | reg_name[i.RType.rs], |
326 | i.RType.rd+1, | 326 | i.RType.shamt, |
327 | i.RType.shamt); | 327 | i.RType.rd+1); |
328 | else if (i.RType.func == OP_INS) | 328 | else if (i.RType.func == OP_INS) |
329 | db_printf("ins\t%s,%s,%d,%d", | 329 | db_printf("ins\t%s,%s,%d,%d", |
330 | reg_name[i.RType.rt], | 330 | reg_name[i.RType.rt], |
331 | reg_name[i.RType.rs], | 331 | reg_name[i.RType.rs], |
332 | i.RType.rd+1, | 332 | i.RType.shamt, |
333 | i.RType.shamt); | 333 | i.RType.rd-i.RType.shamt+1); |
334 | else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH) | 334 | else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH) |
335 | db_printf("wsbh\t%s,%s", | 335 | db_printf("wsbh\t%s,%s", |
336 | reg_name[i.RType.rd], | 336 | reg_name[i.RType.rd], |
diff --git a/libpixelflinger/codeflinger/mips_opcode.h b/libpixelflinger/codeflinger/mips_opcode.h index 7ed5ef579..45bb19ea1 100644 --- a/libpixelflinger/codeflinger/mips_opcode.h +++ b/libpixelflinger/codeflinger/mips_opcode.h | |||
@@ -125,69 +125,118 @@ typedef union { | |||
125 | #define OP_BLEZ 006 | 125 | #define OP_BLEZ 006 |
126 | #define OP_BGTZ 007 | 126 | #define OP_BGTZ 007 |
127 | 127 | ||
128 | #if __mips_isa_rev < 6 | ||
128 | #define OP_ADDI 010 | 129 | #define OP_ADDI 010 |
130 | #else | ||
131 | #define OP_POP10 010 | ||
132 | #endif | ||
133 | |||
129 | #define OP_ADDIU 011 | 134 | #define OP_ADDIU 011 |
130 | #define OP_SLTI 012 | 135 | #define OP_SLTI 012 |
131 | #define OP_SLTIU 013 | 136 | #define OP_SLTIU 013 |
132 | #define OP_ANDI 014 | 137 | #define OP_ANDI 014 |
133 | #define OP_ORI 015 | 138 | #define OP_ORI 015 |
134 | #define OP_XORI 016 | 139 | #define OP_XORI 016 |
140 | |||
141 | #if __mips_isa_rev < 6 | ||
135 | #define OP_LUI 017 | 142 | #define OP_LUI 017 |
143 | #else | ||
144 | #define OP_AUI 017 | ||
145 | #endif | ||
136 | 146 | ||
137 | #define OP_COP0 020 | 147 | #define OP_COP0 020 |
138 | #define OP_COP1 021 | 148 | #define OP_COP1 021 |
139 | #define OP_COP2 022 | 149 | #define OP_COP2 022 |
150 | |||
151 | #if __mips_isa_rev < 6 | ||
140 | #define OP_COP3 023 | 152 | #define OP_COP3 023 |
141 | #define OP_BEQL 024 /* MIPS-II, for r4000 port */ | 153 | #define OP_BEQL 024 |
142 | #define OP_BNEL 025 /* MIPS-II, for r4000 port */ | 154 | #define OP_BNEL 025 |
143 | #define OP_BLEZL 026 /* MIPS-II, for r4000 port */ | 155 | #define OP_BLEZL 026 |
144 | #define OP_BGTZL 027 /* MIPS-II, for r4000 port */ | 156 | #define OP_BGTZL 027 |
157 | #define OP_DADDI 030 | ||
158 | #else | ||
159 | #define OP_POP26 026 | ||
160 | #define OP_POP27 027 | ||
161 | #define OP_POP30 030 | ||
162 | #endif | ||
145 | 163 | ||
146 | #define OP_DADDI 030 /* MIPS-II, for r4000 port */ | 164 | #define OP_DADDIU 031 |
147 | #define OP_DADDIU 031 /* MIPS-II, for r4000 port */ | ||
148 | #define OP_LDL 032 /* MIPS-II, for r4000 port */ | ||
149 | #define OP_LDR 033 /* MIPS-II, for r4000 port */ | ||
150 | 165 | ||
151 | #define OP_SPECIAL2 034 /* QED opcodes */ | 166 | #if __mips_isa_rev < 6 |
152 | #define OP_SPECIAL3 037 /* mips32r2 opcodes */ | 167 | #define OP_LDL 032 |
168 | #define OP_LDR 033 | ||
169 | #define OP_SPECIAL2 034 | ||
170 | #else | ||
171 | #define OP_DAUI 035 | ||
172 | #endif | ||
173 | |||
174 | #define OP_SPECIAL3 037 | ||
153 | 175 | ||
154 | #define OP_LB 040 | 176 | #define OP_LB 040 |
155 | #define OP_LH 041 | 177 | #define OP_LH 041 |
178 | |||
179 | #if __mips_isa_rev < 6 | ||
156 | #define OP_LWL 042 | 180 | #define OP_LWL 042 |
181 | #endif | ||
182 | |||
157 | #define OP_LW 043 | 183 | #define OP_LW 043 |
158 | #define OP_LBU 044 | 184 | #define OP_LBU 044 |
159 | #define OP_LHU 045 | 185 | #define OP_LHU 045 |
160 | #define OP_LWR 046 | 186 | #define OP_LWR 046 |
161 | #define OP_LHU 045 | 187 | #define OP_LHU 045 |
188 | |||
189 | #if __mips_isa_rev < 6 | ||
162 | #define OP_LWR 046 | 190 | #define OP_LWR 046 |
163 | #define OP_LWU 047 /* MIPS-II, for r4000 port */ | 191 | #endif |
192 | |||
193 | #define OP_LWU 047 | ||
164 | 194 | ||
165 | #define OP_SB 050 | 195 | #define OP_SB 050 |
166 | #define OP_SH 051 | 196 | #define OP_SH 051 |
197 | |||
198 | #if __mips_isa_rev < 6 | ||
167 | #define OP_SWL 052 | 199 | #define OP_SWL 052 |
200 | #endif | ||
201 | |||
168 | #define OP_SW 053 | 202 | #define OP_SW 053 |
169 | #define OP_SDL 054 /* MIPS-II, for r4000 port */ | ||
170 | #define OP_SDR 055 /* MIPS-II, for r4000 port */ | ||
171 | #define OP_SWR 056 | ||
172 | #define OP_CACHE 057 /* MIPS-II, for r4000 port */ | ||
173 | 203 | ||
204 | #if __mips_isa_rev < 6 | ||
205 | #define OP_SDL 054 | ||
206 | #define OP_SDR 055 | ||
207 | #define OP_SWR 056 | ||
208 | #define OP_CACHE 057 | ||
174 | #define OP_LL 060 | 209 | #define OP_LL 060 |
175 | #define OP_LWC0 OP_LL /* backwards source compatibility */ | 210 | #define OP_LWC0 OP_LL |
176 | #define OP_LWC1 061 | 211 | #define OP_LWC1 061 |
177 | #define OP_LWC2 062 | 212 | #define OP_LWC2 062 |
178 | #define OP_LWC3 063 | 213 | #define OP_LWC3 063 |
179 | #define OP_LLD 064 /* MIPS-II, for r4000 port */ | 214 | #define OP_LLD 064 |
215 | #else | ||
216 | #define OP_LWC1 061 | ||
217 | #define OP_BC 062 | ||
218 | #endif | ||
219 | |||
180 | #define OP_LDC1 065 | 220 | #define OP_LDC1 065 |
181 | #define OP_LD 067 /* MIPS-II, for r4000 port */ | 221 | #define OP_LD 067 |
182 | 222 | ||
223 | #if __mips_isa_rev < 6 | ||
183 | #define OP_SC 070 | 224 | #define OP_SC 070 |
184 | #define OP_SWC0 OP_SC /* backwards source compatibility */ | 225 | #define OP_SWC0 OP_SC |
226 | #endif | ||
227 | |||
185 | #define OP_SWC1 071 | 228 | #define OP_SWC1 071 |
229 | |||
230 | #if __mips_isa_rev < 6 | ||
186 | #define OP_SWC2 072 | 231 | #define OP_SWC2 072 |
187 | #define OP_SWC3 073 | 232 | #define OP_SWC3 073 |
188 | #define OP_SCD 074 /* MIPS-II, for r4000 port */ | 233 | #define OP_SCD 074 |
234 | #else | ||
235 | #define OP_BALC 072 | ||
236 | #endif | ||
237 | |||
189 | #define OP_SDC1 075 | 238 | #define OP_SDC1 075 |
190 | #define OP_SD 077 /* MIPS-II, for r4000 port */ | 239 | #define OP_SD 077 |
191 | 240 | ||
192 | /* | 241 | /* |
193 | * Values for the 'func' field when 'op' == OP_SPECIAL. | 242 | * Values for the 'func' field when 'op' == OP_SPECIAL. |
@@ -199,28 +248,50 @@ typedef union { | |||
199 | #define OP_SRLV 006 | 248 | #define OP_SRLV 006 |
200 | #define OP_SRAV 007 | 249 | #define OP_SRAV 007 |
201 | 250 | ||
251 | #if __mips_isa_rev < 6 | ||
202 | #define OP_JR 010 | 252 | #define OP_JR 010 |
253 | #endif | ||
254 | |||
203 | #define OP_JALR 011 | 255 | #define OP_JALR 011 |
204 | #define OP_SYSCALL 014 | 256 | #define OP_SYSCALL 014 |
205 | #define OP_BREAK 015 | 257 | #define OP_BREAK 015 |
206 | #define OP_SYNC 017 /* MIPS-II, for r4000 port */ | 258 | #define OP_SYNC 017 |
207 | 259 | ||
260 | #if __mips_isa_rev < 6 | ||
208 | #define OP_MFHI 020 | 261 | #define OP_MFHI 020 |
209 | #define OP_MTHI 021 | 262 | #define OP_MTHI 021 |
210 | #define OP_MFLO 022 | 263 | #define OP_MFLO 022 |
211 | #define OP_MTLO 023 | 264 | #define OP_MTLO 023 |
212 | #define OP_DSLLV 024 /* MIPS-II, for r4000 port */ | 265 | #else |
213 | #define OP_DSRLV 026 /* MIPS-II, for r4000 port */ | 266 | #define OP_CLZ 020 |
214 | #define OP_DSRAV 027 /* MIPS-II, for r4000 port */ | 267 | #define OP_CLO 021 |
268 | #define OP_DCLZ 022 | ||
269 | #define OP_DCLO 023 | ||
270 | #endif | ||
271 | |||
272 | #define OP_DSLLV 024 | ||
273 | #define OP_DSRLV 026 | ||
274 | #define OP_DSRAV 027 | ||
215 | 275 | ||
276 | #if __mips_isa_rev < 6 | ||
216 | #define OP_MULT 030 | 277 | #define OP_MULT 030 |
217 | #define OP_MULTU 031 | 278 | #define OP_MULTU 031 |
218 | #define OP_DIV 032 | 279 | #define OP_DIV 032 |
219 | #define OP_DIVU 033 | 280 | #define OP_DIVU 033 |
220 | #define OP_DMULT 034 /* MIPS-II, for r4000 port */ | 281 | #define OP_DMULT 034 |
221 | #define OP_DMULTU 035 /* MIPS-II, for r4000 port */ | 282 | #define OP_DMULTU 035 |
222 | #define OP_DDIV 036 /* MIPS-II, for r4000 port */ | 283 | #define OP_DDIV 036 |
223 | #define OP_DDIVU 037 /* MIPS-II, for r4000 port */ | 284 | #define OP_DDIVU 037 |
285 | #else | ||
286 | #define OP_SOP30 030 | ||
287 | #define OP_SOP31 031 | ||
288 | #define OP_SOP32 032 | ||
289 | #define OP_SOP33 033 | ||
290 | #define OP_SOP34 034 | ||
291 | #define OP_SOP35 035 | ||
292 | #define OP_SOP36 036 | ||
293 | #define OP_SOP37 037 | ||
294 | #endif | ||
224 | 295 | ||
225 | #define OP_ADD 040 | 296 | #define OP_ADD 040 |
226 | #define OP_ADDU 041 | 297 | #define OP_ADDU 041 |
@@ -233,73 +304,96 @@ typedef union { | |||
233 | 304 | ||
234 | #define OP_SLT 052 | 305 | #define OP_SLT 052 |
235 | #define OP_SLTU 053 | 306 | #define OP_SLTU 053 |
236 | #define OP_DADD 054 /* MIPS-II, for r4000 port */ | 307 | #define OP_DADD 054 |
237 | #define OP_DADDU 055 /* MIPS-II, for r4000 port */ | 308 | #define OP_DADDU 055 |
238 | #define OP_DSUB 056 /* MIPS-II, for r4000 port */ | 309 | #define OP_DSUB 056 |
239 | #define OP_DSUBU 057 /* MIPS-II, for r4000 port */ | 310 | #define OP_DSUBU 057 |
240 | 311 | ||
241 | #define OP_TGE 060 /* MIPS-II, for r4000 port */ | 312 | #define OP_TGE 060 |
242 | #define OP_TGEU 061 /* MIPS-II, for r4000 port */ | 313 | #define OP_TGEU 061 |
243 | #define OP_TLT 062 /* MIPS-II, for r4000 port */ | 314 | #define OP_TLT 062 |
244 | #define OP_TLTU 063 /* MIPS-II, for r4000 port */ | 315 | #define OP_TLTU 063 |
245 | #define OP_TEQ 064 /* MIPS-II, for r4000 port */ | 316 | #define OP_TEQ 064 |
246 | #define OP_TNE 066 /* MIPS-II, for r4000 port */ | 317 | #define OP_TNE 066 |
247 | 318 | ||
248 | #define OP_DSLL 070 /* MIPS-II, for r4000 port */ | 319 | #define OP_DSLL 070 |
249 | #define OP_DSRL 072 /* MIPS-II, for r4000 port */ | 320 | #define OP_DSRL 072 |
250 | #define OP_DSRA 073 /* MIPS-II, for r4000 port */ | 321 | #define OP_DSRA 073 |
251 | #define OP_DSLL32 074 /* MIPS-II, for r4000 port */ | 322 | #define OP_DSLL32 074 |
252 | #define OP_DSRL32 076 /* MIPS-II, for r4000 port */ | 323 | #define OP_DSRL32 076 |
253 | #define OP_DSRA32 077 /* MIPS-II, for r4000 port */ | 324 | #define OP_DSRA32 077 |
254 | 325 | ||
326 | #if __mips_isa_rev < 6 | ||
255 | /* | 327 | /* |
256 | * Values for the 'func' field when 'op' == OP_SPECIAL2. | 328 | * Values for the 'func' field when 'op' == OP_SPECIAL2. |
329 | * OP_SPECIAL2 opcodes are removed in mips32r6 | ||
257 | */ | 330 | */ |
258 | #define OP_MAD 000 /* QED */ | 331 | #define OP_MAD 000 /* QED */ |
259 | #define OP_MADU 001 /* QED */ | 332 | #define OP_MADU 001 /* QED */ |
260 | #define OP_MUL 002 /* QED */ | 333 | #define OP_MUL 002 /* QED */ |
334 | #endif | ||
261 | 335 | ||
262 | /* | 336 | /* |
263 | * Values for the 'func' field when 'op' == OP_SPECIAL3. | 337 | * Values for the 'func' field when 'op' == OP_SPECIAL3. |
264 | */ | 338 | */ |
265 | #define OP_EXT 000 | 339 | #define OP_EXT 000 |
340 | #define OP_DEXTM 001 | ||
341 | #define OP_DEXTU 002 | ||
342 | #define OP_DEXT 003 | ||
266 | #define OP_INS 004 | 343 | #define OP_INS 004 |
344 | #define OP_DINSM 005 | ||
345 | #define OP_DINSU 006 | ||
346 | #define OP_DINS 007 | ||
267 | #define OP_BSHFL 040 | 347 | #define OP_BSHFL 040 |
348 | #define OP_RDHWR 073 | ||
268 | 349 | ||
269 | /* | 350 | /* |
270 | * Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL. | 351 | * Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL. |
271 | */ | 352 | */ |
353 | |||
272 | #define OP_WSBH 002 | 354 | #define OP_WSBH 002 |
273 | #define OP_SEB 020 | 355 | #define OP_SEB 020 |
274 | #define OP_SEH 030 | 356 | #define OP_SEH 030 |
275 | 357 | ||
358 | #if __mips_isa_rev == 6 | ||
359 | /* | ||
360 | * Values for the 'shamt' field when OP_SOP30. | ||
361 | */ | ||
362 | #define OP_MUL 002 | ||
363 | #define OP_MUH 003 | ||
364 | #endif | ||
365 | |||
276 | /* | 366 | /* |
277 | * Values for the 'func' field when 'op' == OP_BCOND. | 367 | * Values for the 'func' field when 'op' == OP_BCOND. |
278 | */ | 368 | */ |
279 | #define OP_BLTZ 000 | 369 | #define OP_BLTZ 000 |
280 | #define OP_BGEZ 001 | 370 | #define OP_BGEZ 001 |
281 | #define OP_BLTZL 002 /* MIPS-II, for r4000 port */ | ||
282 | #define OP_BGEZL 003 /* MIPS-II, for r4000 port */ | ||
283 | 371 | ||
284 | #define OP_TGEI 010 /* MIPS-II, for r4000 port */ | 372 | #if __mips_isa_rev < 6 |
285 | #define OP_TGEIU 011 /* MIPS-II, for r4000 port */ | 373 | #define OP_BLTZL 002 |
286 | #define OP_TLTI 012 /* MIPS-II, for r4000 port */ | 374 | #define OP_BGEZL 003 |
287 | #define OP_TLTIU 013 /* MIPS-II, for r4000 port */ | 375 | #define OP_TGEI 010 |
288 | #define OP_TEQI 014 /* MIPS-II, for r4000 port */ | 376 | #define OP_TGEIU 011 |
289 | #define OP_TNEI 016 /* MIPS-II, for r4000 port */ | 377 | #define OP_TLTI 012 |
290 | 378 | #define OP_TLTIU 013 | |
291 | #define OP_BLTZAL 020 /* MIPS-II, for r4000 port */ | 379 | #define OP_TEQI 014 |
380 | #define OP_TNEI 016 | ||
381 | #define OP_BLTZAL 020 | ||
292 | #define OP_BGEZAL 021 | 382 | #define OP_BGEZAL 021 |
293 | #define OP_BLTZALL 022 | 383 | #define OP_BLTZALL 022 |
294 | #define OP_BGEZALL 023 | 384 | #define OP_BGEZALL 023 |
385 | #else | ||
386 | #define OP_NAL 020 | ||
387 | #define OP_BAL 021 | ||
388 | #endif | ||
295 | 389 | ||
296 | /* | 390 | /* |
297 | * Values for the 'rs' field when 'op' == OP_COPz. | 391 | * Values for the 'rs' field when 'op' == OP_COPz. |
298 | */ | 392 | */ |
299 | #define OP_MF 000 | 393 | #define OP_MF 000 |
300 | #define OP_DMF 001 /* MIPS-II, for r4000 port */ | 394 | #define OP_DMF 001 |
301 | #define OP_MT 004 | 395 | #define OP_MT 004 |
302 | #define OP_DMT 005 /* MIPS-II, for r4000 port */ | 396 | #define OP_DMT 005 |
303 | #define OP_BCx 010 | 397 | #define OP_BCx 010 |
304 | #define OP_BCy 014 | 398 | #define OP_BCy 014 |
305 | #define OP_CF 002 | 399 | #define OP_CF 002 |
@@ -311,6 +405,6 @@ typedef union { | |||
311 | #define COPz_BC_TF_MASK 0x01 | 405 | #define COPz_BC_TF_MASK 0x01 |
312 | #define COPz_BC_TRUE 0x01 | 406 | #define COPz_BC_TRUE 0x01 |
313 | #define COPz_BC_FALSE 0x00 | 407 | #define COPz_BC_FALSE 0x00 |
314 | #define COPz_BCL_TF_MASK 0x02 /* MIPS-II, for r4000 port */ | 408 | #define COPz_BCL_TF_MASK 0x02 |
315 | #define COPz_BCL_TRUE 0x02 /* MIPS-II, for r4000 port */ | 409 | #define COPz_BCL_TRUE 0x02 |
316 | #define COPz_BCL_FALSE 0x00 /* MIPS-II, for r4000 port */ | 410 | #define COPz_BCL_FALSE 0x00 |
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h index d43655cbb..56a6edbea 100644 --- a/libpixelflinger/include/private/pixelflinger/ggl_context.h +++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h | |||
@@ -42,7 +42,7 @@ inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { | |||
42 | #else | 42 | #else |
43 | 43 | ||
44 | inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { | 44 | inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { |
45 | #if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 | 45 | #if defined(__mips__) && __mips_isa_rev>=2 |
46 | uint32_t r; | 46 | uint32_t r; |
47 | __asm__("wsbh %0, %1;" | 47 | __asm__("wsbh %0, %1;" |
48 | "rotr %0, %0, 16" | 48 | "rotr %0, %0, 16" |
@@ -55,7 +55,7 @@ inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { | |||
55 | #endif | 55 | #endif |
56 | } | 56 | } |
57 | inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { | 57 | inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { |
58 | #if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 | 58 | #if defined(__mips__) && __mips_isa_rev>=2 |
59 | uint32_t r; | 59 | uint32_t r; |
60 | __asm__("wsbh %0, %1;" | 60 | __asm__("wsbh %0, %1;" |
61 | "rotr %0, %0, 16" | 61 | "rotr %0, %0, 16" |
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h index 787f6202b..17b85dd58 100644 --- a/libpixelflinger/include/private/pixelflinger/ggl_fixed.h +++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h | |||
@@ -520,6 +520,252 @@ inline int64_t gglMulii(int32_t x, int32_t y) | |||
520 | return res; | 520 | return res; |
521 | } | 521 | } |
522 | 522 | ||
523 | #elif defined(__mips__) && __mips_isa_rev == 6 | ||
524 | |||
525 | /*inline MIPS implementations*/ | ||
526 | inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST; | ||
527 | inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) { | ||
528 | GGLfixed result,tmp,tmp1,tmp2; | ||
529 | |||
530 | if (__builtin_constant_p(shift)) { | ||
531 | if (shift == 0) { | ||
532 | asm ("mul %[res], %[a], %[b] \t\n" | ||
533 | : [res]"=&r"(result) | ||
534 | : [a]"r"(a),[b]"r"(b) | ||
535 | ); | ||
536 | } else if (shift == 32) | ||
537 | { | ||
538 | asm ("mul %[res], %[a], %[b] \t\n" | ||
539 | "li %[tmp],1\t\n" | ||
540 | "sll %[tmp],%[tmp],0x1f\t\n" | ||
541 | "addu %[tmp1],%[tmp],%[res] \t\n" | ||
542 | "muh %[res], %[a], %[b] \t\n" | ||
543 | "sltu %[tmp1],%[tmp1],%[tmp]\t\n" /*obit*/ | ||
544 | "sra %[tmp],%[tmp],0x1f \t\n" | ||
545 | "addu %[res],%[res],%[tmp]\t\n" | ||
546 | "addu %[res],%[res],%[tmp1]\t\n" | ||
547 | : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1) | ||
548 | : [a]"r"(a),[b]"r"(b),[shift]"I"(shift) | ||
549 | ); | ||
550 | } else if ((shift >0) && (shift < 32)) | ||
551 | { | ||
552 | asm ("mul %[res], %[a], %[b] \t\n" | ||
553 | "li %[tmp],1 \t\n" | ||
554 | "sll %[tmp],%[tmp],%[shiftm1] \t\n" | ||
555 | "addu %[tmp1],%[tmp],%[res] \t\n" | ||
556 | "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/ | ||
557 | "addu %[res],%[res],%[tmp] \t\n" | ||
558 | "muh %[tmp], %[a], %[b] \t\n" | ||
559 | "addu %[tmp],%[tmp],%[tmp1] \t\n" | ||
560 | "sll %[tmp],%[tmp],%[lshift] \t\n" | ||
561 | "srl %[res],%[res],%[rshift] \t\n" | ||
562 | "or %[res],%[res],%[tmp] \t\n" | ||
563 | : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
564 | : [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1) | ||
565 | ); | ||
566 | } else { | ||
567 | asm ("mul %[res], %[a], %[b] \t\n" | ||
568 | "li %[tmp],1 \t\n" | ||
569 | "sll %[tmp],%[tmp],%[shiftm1] \t\n" | ||
570 | "addu %[tmp1],%[tmp],%[res] \t\n" | ||
571 | "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/ | ||
572 | "sra %[tmp2],%[tmp],0x1f \t\n" | ||
573 | "addu %[res],%[res],%[tmp] \t\n" | ||
574 | "muh %[tmp], %[a], %[b] \t\n" | ||
575 | "addu %[tmp],%[tmp],%[tmp2] \t\n" | ||
576 | "addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/ | ||
577 | "srl %[tmp2],%[res],%[rshift] \t\n" | ||
578 | "srav %[res], %[tmp],%[rshift]\t\n" | ||
579 | "sll %[tmp],%[tmp],1 \t\n" | ||
580 | "sll %[tmp],%[tmp],%[norbits] \t\n" | ||
581 | "or %[tmp],%[tmp],%[tmp2] \t\n" | ||
582 | "seleqz %[tmp],%[tmp],%[bit5] \t\n" | ||
583 | "selnez %[res],%[res],%[bit5] \t\n" | ||
584 | "or %[res],%[res],%[tmp] \t\n" | ||
585 | : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
586 | : [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20) | ||
587 | ); | ||
588 | } | ||
589 | } else { | ||
590 | asm ("mul %[res], %[a], %[b] \t\n" | ||
591 | "li %[tmp],1 \t\n" | ||
592 | "sll %[tmp],%[tmp],%[shiftm1] \t\n" | ||
593 | "addu %[tmp1],%[tmp],%[res] \t\n" | ||
594 | "sltu %[tmp1],%[tmp1],%[tmp] \t\n" /*obit?*/ | ||
595 | "sra %[tmp2],%[tmp],0x1f \t\n" | ||
596 | "addu %[res],%[res],%[tmp] \t\n" | ||
597 | "muh %[tmp], %[a], %[b] \t\n" | ||
598 | "addu %[tmp],%[tmp],%[tmp2] \t\n" | ||
599 | "addu %[tmp],%[tmp],%[tmp1] \t\n" /*tmp=hi*/ | ||
600 | "srl %[tmp2],%[res],%[rshift] \t\n" | ||
601 | "srav %[res], %[tmp],%[rshift]\t\n" | ||
602 | "sll %[tmp],%[tmp],1 \t\n" | ||
603 | "sll %[tmp],%[tmp],%[norbits] \t\n" | ||
604 | "or %[tmp],%[tmp],%[tmp2] \t\n" | ||
605 | "seleqz %[tmp],%[tmp],%[bit5] \t\n" | ||
606 | "selnez %[res],%[res],%[bit5] \t\n" | ||
607 | "or %[res],%[res],%[tmp] \t\n" | ||
608 | : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
609 | : [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20) | ||
610 | ); | ||
611 | } | ||
612 | return result; | ||
613 | } | ||
614 | |||
615 | inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST; | ||
616 | inline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) { | ||
617 | GGLfixed result,t,tmp1,tmp2; | ||
618 | |||
619 | if (__builtin_constant_p(shift)) { | ||
620 | if (shift == 0) { | ||
621 | asm ("mul %[lo], %[a], %[b] \t\n" | ||
622 | "addu %[lo],%[lo],%[c] \t\n" | ||
623 | : [lo]"=&r"(result) | ||
624 | : [a]"r"(a),[b]"r"(b),[c]"r"(c) | ||
625 | ); | ||
626 | } else if (shift == 32) { | ||
627 | asm ("muh %[lo], %[a], %[b] \t\n" | ||
628 | "addu %[lo],%[lo],%[c] \t\n" | ||
629 | : [lo]"=&r"(result) | ||
630 | : [a]"r"(a),[b]"r"(b),[c]"r"(c) | ||
631 | ); | ||
632 | } else if ((shift>0) && (shift<32)) { | ||
633 | asm ("mul %[res], %[a], %[b] \t\n" | ||
634 | "muh %[t], %[a], %[b] \t\n" | ||
635 | "srl %[res],%[res],%[rshift] \t\n" | ||
636 | "sll %[t],%[t],%[lshift] \t\n" | ||
637 | "or %[res],%[res],%[t] \t\n" | ||
638 | "addu %[res],%[res],%[c] \t\n" | ||
639 | : [res]"=&r"(result),[t]"=&r"(t) | ||
640 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift) | ||
641 | ); | ||
642 | } else { | ||
643 | asm ("mul %[res], %[a], %[b] \t\n" | ||
644 | "muh %[t], %[a], %[b] \t\n" | ||
645 | "nor %[tmp1],$zero,%[shift]\t\n" | ||
646 | "srl %[res],%[res],%[shift] \t\n" | ||
647 | "sll %[tmp2],%[t],1 \t\n" | ||
648 | "sllv %[tmp2],%[tmp2],%[tmp1] \t\n" | ||
649 | "or %[tmp1],%[tmp2],%[res] \t\n" | ||
650 | "srav %[res],%[t],%[shift] \t\n" | ||
651 | "andi %[tmp2],%[shift],0x20\t\n" | ||
652 | "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n" | ||
653 | "selnez %[res],%[res],%[tmp2]\t\n" | ||
654 | "or %[res],%[res],%[tmp1]\t\n" | ||
655 | "addu %[res],%[res],%[c] \t\n" | ||
656 | : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
657 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift) | ||
658 | ); | ||
659 | } | ||
660 | } else { | ||
661 | asm ("mul %[res], %[a], %[b] \t\n" | ||
662 | "muh %[t], %[a], %[b] \t\n" | ||
663 | "nor %[tmp1],$zero,%[shift]\t\n" | ||
664 | "srl %[res],%[res],%[shift] \t\n" | ||
665 | "sll %[tmp2],%[t],1 \t\n" | ||
666 | "sllv %[tmp2],%[tmp2],%[tmp1] \t\n" | ||
667 | "or %[tmp1],%[tmp2],%[res] \t\n" | ||
668 | "srav %[res],%[t],%[shift] \t\n" | ||
669 | "andi %[tmp2],%[shift],0x20\t\n" | ||
670 | "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n" | ||
671 | "selnez %[res],%[res],%[tmp2]\t\n" | ||
672 | "or %[res],%[res],%[tmp1]\t\n" | ||
673 | "addu %[res],%[res],%[c] \t\n" | ||
674 | : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
675 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift) | ||
676 | ); | ||
677 | } | ||
678 | return result; | ||
679 | } | ||
680 | |||
681 | inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST; | ||
682 | inline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) { | ||
683 | GGLfixed result,t,tmp1,tmp2; | ||
684 | |||
685 | if (__builtin_constant_p(shift)) { | ||
686 | if (shift == 0) { | ||
687 | asm ("mul %[lo], %[a], %[b] \t\n" | ||
688 | "subu %[lo],%[lo],%[c] \t\n" | ||
689 | : [lo]"=&r"(result) | ||
690 | : [a]"r"(a),[b]"r"(b),[c]"r"(c) | ||
691 | ); | ||
692 | } else if (shift == 32) { | ||
693 | asm ("muh %[lo], %[a], %[b] \t\n" | ||
694 | "subu %[lo],%[lo],%[c] \t\n" | ||
695 | : [lo]"=&r"(result) | ||
696 | : [a]"r"(a),[b]"r"(b),[c]"r"(c) | ||
697 | ); | ||
698 | } else if ((shift>0) && (shift<32)) { | ||
699 | asm ("mul %[res], %[a], %[b] \t\n" | ||
700 | "muh %[t], %[a], %[b] \t\n" | ||
701 | "srl %[res],%[res],%[rshift] \t\n" | ||
702 | "sll %[t],%[t],%[lshift] \t\n" | ||
703 | "or %[res],%[res],%[t] \t\n" | ||
704 | "subu %[res],%[res],%[c] \t\n" | ||
705 | : [res]"=&r"(result),[t]"=&r"(t) | ||
706 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift) | ||
707 | ); | ||
708 | } else { | ||
709 | asm ("mul %[res], %[a], %[b] \t\n" | ||
710 | "muh %[t], %[a], %[b] \t\n" | ||
711 | "nor %[tmp1],$zero,%[shift]\t\n" | ||
712 | "srl %[res],%[res],%[shift] \t\n" | ||
713 | "sll %[tmp2],%[t],1 \t\n" | ||
714 | "sllv %[tmp2],%[tmp2],%[tmp1] \t\n" | ||
715 | "or %[tmp1],%[tmp2],%[res] \t\n" | ||
716 | "srav %[res],%[t],%[shift] \t\n" | ||
717 | "andi %[tmp2],%[shift],0x20\t\n" | ||
718 | "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n" | ||
719 | "selnez %[res],%[res],%[tmp2]\t\n" | ||
720 | "or %[res],%[res],%[tmp1]\t\n" | ||
721 | "subu %[res],%[res],%[c] \t\n" | ||
722 | : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
723 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift) | ||
724 | ); | ||
725 | } | ||
726 | } else { | ||
727 | asm ("mul %[res], %[a], %[b] \t\n" | ||
728 | "muh %[t], %[a], %[b] \t\n" | ||
729 | "nor %[tmp1],$zero,%[shift]\t\n" | ||
730 | "srl %[res],%[res],%[shift] \t\n" | ||
731 | "sll %[tmp2],%[t],1 \t\n" | ||
732 | "sllv %[tmp2],%[tmp2],%[tmp1] \t\n" | ||
733 | "or %[tmp1],%[tmp2],%[res] \t\n" | ||
734 | "srav %[res],%[t],%[shift] \t\n" | ||
735 | "andi %[tmp2],%[shift],0x20\t\n" | ||
736 | "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n" | ||
737 | "selnez %[res],%[res],%[tmp2]\t\n" | ||
738 | "or %[res],%[res],%[tmp1]\t\n" | ||
739 | "subu %[res],%[res],%[c] \t\n" | ||
740 | : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2) | ||
741 | : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift) | ||
742 | ); | ||
743 | } | ||
744 | return result; | ||
745 | } | ||
746 | |||
747 | inline int64_t gglMulii(int32_t x, int32_t y) CONST; | ||
748 | inline int64_t gglMulii(int32_t x, int32_t y) { | ||
749 | union { | ||
750 | struct { | ||
751 | #if defined(__MIPSEL__) | ||
752 | int32_t lo; | ||
753 | int32_t hi; | ||
754 | #elif defined(__MIPSEB__) | ||
755 | int32_t hi; | ||
756 | int32_t lo; | ||
757 | #endif | ||
758 | } s; | ||
759 | int64_t res; | ||
760 | }u; | ||
761 | asm("mul %0, %2, %3 \t\n" | ||
762 | "muh %1, %2, %3 \t\n" | ||
763 | : "=r"(u.s.lo), "=&r"(u.s.hi) | ||
764 | : "%r"(x), "r"(y) | ||
765 | ); | ||
766 | return u.res; | ||
767 | } | ||
768 | |||
523 | #else // ---------------------------------------------------------------------- | 769 | #else // ---------------------------------------------------------------------- |
524 | 770 | ||
525 | inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST; | 771 | inline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST; |
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp index 3d145319a..a718b02c6 100644 --- a/libpixelflinger/scanline.cpp +++ b/libpixelflinger/scanline.cpp | |||
@@ -41,6 +41,8 @@ | |||
41 | #include "codeflinger/Arm64Assembler.h" | 41 | #include "codeflinger/Arm64Assembler.h" |
42 | #elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 42 | #elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 |
43 | #include "codeflinger/MIPSAssembler.h" | 43 | #include "codeflinger/MIPSAssembler.h" |
44 | #elif defined(__mips__) && defined(__LP64__) | ||
45 | #include "codeflinger/MIPS64Assembler.h" | ||
44 | #endif | 46 | #endif |
45 | //#include "codeflinger/ARMAssemblerOptimizer.h" | 47 | //#include "codeflinger/ARMAssemblerOptimizer.h" |
46 | 48 | ||
@@ -59,7 +61,7 @@ | |||
59 | # define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED | 61 | # define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED |
60 | #endif | 62 | #endif |
61 | 63 | ||
62 | #if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__) | 64 | #if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))) || defined(__aarch64__) |
63 | # define ANDROID_ARM_CODEGEN 1 | 65 | # define ANDROID_ARM_CODEGEN 1 |
64 | #else | 66 | #else |
65 | # define ANDROID_ARM_CODEGEN 0 | 67 | # define ANDROID_ARM_CODEGEN 0 |
@@ -73,7 +75,7 @@ | |||
73 | */ | 75 | */ |
74 | #define DEBUG_NEEDS 0 | 76 | #define DEBUG_NEEDS 0 |
75 | 77 | ||
76 | #if defined( __mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 78 | #if defined( __mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)) |
77 | #define ASSEMBLY_SCRATCH_SIZE 4096 | 79 | #define ASSEMBLY_SCRATCH_SIZE 4096 |
78 | #elif defined(__aarch64__) | 80 | #elif defined(__aarch64__) |
79 | #define ASSEMBLY_SCRATCH_SIZE 8192 | 81 | #define ASSEMBLY_SCRATCH_SIZE 8192 |
@@ -136,6 +138,9 @@ extern "C" void scanline_t32cb16blend_arm64(uint16_t*, uint32_t*, size_t); | |||
136 | extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct); | 138 | extern "C" void scanline_col32cb16blend_arm64(uint16_t *dst, uint32_t col, size_t ct); |
137 | #elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 139 | #elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 |
138 | extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t); | 140 | extern "C" void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t); |
141 | #elif defined(__mips__) && defined(__LP64__) | ||
142 | extern "C" void scanline_t32cb16blend_mips64(uint16_t*, uint32_t*, size_t); | ||
143 | extern "C" void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t col, size_t ct); | ||
139 | #endif | 144 | #endif |
140 | 145 | ||
141 | // ---------------------------------------------------------------------------- | 146 | // ---------------------------------------------------------------------------- |
@@ -286,7 +291,7 @@ static const needs_filter_t fill16noblend = { | |||
286 | 291 | ||
287 | #if ANDROID_ARM_CODEGEN | 292 | #if ANDROID_ARM_CODEGEN |
288 | 293 | ||
289 | #if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 294 | #if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__)) |
290 | static CodeCache gCodeCache(32 * 1024); | 295 | static CodeCache gCodeCache(32 * 1024); |
291 | #elif defined(__aarch64__) | 296 | #elif defined(__aarch64__) |
292 | static CodeCache gCodeCache(48 * 1024); | 297 | static CodeCache gCodeCache(48 * 1024); |
@@ -406,8 +411,10 @@ static void pick_scanline(context_t* c) | |||
406 | //GGLAssembler assembler( | 411 | //GGLAssembler assembler( |
407 | // new ARMAssemblerOptimizer(new ARMAssembler(a)) ); | 412 | // new ARMAssemblerOptimizer(new ARMAssembler(a)) ); |
408 | #endif | 413 | #endif |
409 | #if defined(__mips__) | 414 | #if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 |
410 | GGLAssembler assembler( new ArmToMipsAssembler(a) ); | 415 | GGLAssembler assembler( new ArmToMipsAssembler(a) ); |
416 | #elif defined(__mips__) && defined(__LP64__) | ||
417 | GGLAssembler assembler( new ArmToMips64Assembler(a) ); | ||
411 | #elif defined(__aarch64__) | 418 | #elif defined(__aarch64__) |
412 | GGLAssembler assembler( new ArmToArm64Assembler(a) ); | 419 | GGLAssembler assembler( new ArmToArm64Assembler(a) ); |
413 | #endif | 420 | #endif |
@@ -2103,6 +2110,8 @@ void scanline_col32cb16blend(context_t* c) | |||
2103 | #endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN | 2110 | #endif // defined(__ARM_HAVE_NEON) && BYTE_ORDER == LITTLE_ENDIAN |
2104 | #elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__)) | 2111 | #elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && defined(__aarch64__)) |
2105 | scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); | 2112 | scanline_col32cb16blend_arm64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); |
2113 | #elif ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__mips__) && defined(__LP64__))) | ||
2114 | scanline_col32cb16blend_mips64(dst, GGL_RGBA_TO_HOST(c->packed8888), ct); | ||
2106 | #else | 2115 | #else |
2107 | uint32_t s = GGL_RGBA_TO_HOST(c->packed8888); | 2116 | uint32_t s = GGL_RGBA_TO_HOST(c->packed8888); |
2108 | int sA = (s>>24); | 2117 | int sA = (s>>24); |
@@ -2175,7 +2184,8 @@ last_one: | |||
2175 | 2184 | ||
2176 | void scanline_t32cb16blend(context_t* c) | 2185 | void scanline_t32cb16blend(context_t* c) |
2177 | { | 2186 | { |
2178 | #if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__))) | 2187 | #if ((ANDROID_CODEGEN >= ANDROID_CODEGEN_ASM) && (defined(__arm__) || defined(__aarch64__) || \ |
2188 | (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || defined(__LP64__))))) | ||
2179 | int32_t x = c->iterators.xl; | 2189 | int32_t x = c->iterators.xl; |
2180 | size_t ct = c->iterators.xr - x; | 2190 | size_t ct = c->iterators.xr - x; |
2181 | int32_t y = c->iterators.y; | 2191 | int32_t y = c->iterators.y; |
@@ -2191,8 +2201,10 @@ void scanline_t32cb16blend(context_t* c) | |||
2191 | scanline_t32cb16blend_arm(dst, src, ct); | 2201 | scanline_t32cb16blend_arm(dst, src, ct); |
2192 | #elif defined(__aarch64__) | 2202 | #elif defined(__aarch64__) |
2193 | scanline_t32cb16blend_arm64(dst, src, ct); | 2203 | scanline_t32cb16blend_arm64(dst, src, ct); |
2194 | #elif defined(__mips__) | 2204 | #elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 |
2195 | scanline_t32cb16blend_mips(dst, src, ct); | 2205 | scanline_t32cb16blend_mips(dst, src, ct); |
2206 | #elif defined(__mips__) && defined(__LP64__) | ||
2207 | scanline_t32cb16blend_mips64(dst, src, ct); | ||
2196 | #endif | 2208 | #endif |
2197 | #else | 2209 | #else |
2198 | dst_iterator16 di(c); | 2210 | dst_iterator16 di(c); |
diff --git a/libpixelflinger/tests/arch-mips/Android.mk b/libpixelflinger/tests/arch-mips/Android.mk new file mode 100644 index 000000000..fe6979ef6 --- /dev/null +++ b/libpixelflinger/tests/arch-mips/Android.mk | |||
@@ -0,0 +1,6 @@ | |||
1 | ifeq ($(TARGET_ARCH),mips) | ||
2 | include $(all-subdir-makefiles) | ||
3 | endif | ||
4 | ifeq ($(TARGET_ARCH),mipsel) | ||
5 | include $(all-subdir-makefiles) | ||
6 | endif | ||
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk new file mode 100644 index 000000000..40f197f3b --- /dev/null +++ b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk | |||
@@ -0,0 +1,18 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | col32cb16blend_test.c \ | ||
6 | ../../../arch-mips/col32cb16blend.S | ||
7 | |||
8 | LOCAL_SHARED_LIBRARIES := | ||
9 | |||
10 | LOCAL_C_INCLUDES := | ||
11 | |||
12 | LOCAL_MODULE:= test-pixelflinger-mips-col32cb16blend | ||
13 | |||
14 | LOCAL_MODULE_TAGS := tests | ||
15 | |||
16 | LOCAL_MULTILIB := 32 | ||
17 | |||
18 | include $(BUILD_NATIVE_TEST) | ||
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c new file mode 100644 index 000000000..dd0e60fef --- /dev/null +++ b/libpixelflinger/tests/arch-mips/col32cb16blend/col32cb16blend_test.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 The Android Open Source Project | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in | ||
12 | * the documentation and/or other materials provided with the | ||
13 | * distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | * SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | #include <assert.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
32 | #include <string.h> | ||
33 | #include <inttypes.h> | ||
34 | |||
35 | |||
36 | #define ARGB_8888_MAX 0xFFFFFFFF | ||
37 | #define ARGB_8888_MIN 0x00000000 | ||
38 | #define RGB_565_MAX 0xFFFF | ||
39 | #define RGB_565_MIN 0x0000 | ||
40 | |||
41 | struct test_t | ||
42 | { | ||
43 | char name[256]; | ||
44 | uint32_t src_color; | ||
45 | uint16_t dst_color; | ||
46 | size_t count; | ||
47 | }; | ||
48 | |||
49 | struct test_t tests[] = | ||
50 | { | ||
51 | {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1}, | ||
52 | {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2}, | ||
53 | {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3}, | ||
54 | {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4}, | ||
55 | {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1}, | ||
56 | {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2}, | ||
57 | {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3}, | ||
58 | {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4}, | ||
59 | {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5}, | ||
60 | {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10} | ||
61 | }; | ||
62 | |||
63 | void scanline_col32cb16blend_mips(uint16_t *dst, uint32_t src, size_t count); | ||
64 | void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count) | ||
65 | { | ||
66 | uint32_t srcAlpha = (src>>24); | ||
67 | uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7)); | ||
68 | |||
69 | while (count--) | ||
70 | { | ||
71 | uint16_t d = *dst; | ||
72 | int dstR = (d>>11)&0x1f; | ||
73 | int dstG = (d>>5)&0x3f; | ||
74 | int dstB = (d)&0x1f; | ||
75 | int srcR = (src >> ( 3))&0x1F; | ||
76 | int srcG = (src >> ( 8+2))&0x3F; | ||
77 | int srcB = (src >> (16+3))&0x1F; | ||
78 | srcR += (f*dstR)>>8; | ||
79 | srcG += (f*dstG)>>8; | ||
80 | srcB += (f*dstB)>>8; | ||
81 | *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void scanline_col32cb16blend_test() | ||
86 | { | ||
87 | uint16_t dst_c[16], dst_asm[16]; | ||
88 | uint32_t i, j; | ||
89 | |||
90 | for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i) | ||
91 | { | ||
92 | struct test_t test = tests[i]; | ||
93 | |||
94 | printf("Testing - %s:",test.name); | ||
95 | |||
96 | memset(dst_c, 0, sizeof(dst_c)); | ||
97 | memset(dst_asm, 0, sizeof(dst_asm)); | ||
98 | |||
99 | for(j = 0; j < test.count; ++j) | ||
100 | { | ||
101 | dst_c[j] = test.dst_color; | ||
102 | dst_asm[j] = test.dst_color; | ||
103 | } | ||
104 | |||
105 | |||
106 | scanline_col32cb16blend_c(dst_c, test.src_color, test.count); | ||
107 | scanline_col32cb16blend_mips(dst_asm, test.src_color, test.count); | ||
108 | |||
109 | if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0) | ||
110 | printf("Passed\n"); | ||
111 | else | ||
112 | printf("Failed\n"); | ||
113 | |||
114 | for(j = 0; j < test.count; ++j) | ||
115 | { | ||
116 | printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]); | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | |||
121 | int main() | ||
122 | { | ||
123 | scanline_col32cb16blend_test(); | ||
124 | return 0; | ||
125 | } | ||
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk new file mode 100644 index 000000000..d0c0ae4dc --- /dev/null +++ b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk | |||
@@ -0,0 +1,18 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | t32cb16blend_test.c \ | ||
6 | ../../../arch-mips/t32cb16blend.S | ||
7 | |||
8 | LOCAL_SHARED_LIBRARIES := | ||
9 | |||
10 | LOCAL_C_INCLUDES := | ||
11 | |||
12 | LOCAL_MODULE:= test-pixelflinger-mips-t32cb16blend | ||
13 | |||
14 | LOCAL_MODULE_TAGS := tests | ||
15 | |||
16 | LOCAL_MULTILIB := 32 | ||
17 | |||
18 | include $(BUILD_NATIVE_TEST) | ||
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c new file mode 100644 index 000000000..c6d6937c6 --- /dev/null +++ b/libpixelflinger/tests/arch-mips/t32cb16blend/t32cb16blend_test.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 The Android Open Source Project | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in | ||
12 | * the documentation and/or other materials provided with the | ||
13 | * distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | * SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | #include <assert.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
32 | #include <string.h> | ||
33 | #include <inttypes.h> | ||
34 | |||
35 | #define ARGB_8888_MAX 0xFFFFFFFF | ||
36 | #define ARGB_8888_MIN 0x00000000 | ||
37 | #define RGB_565_MAX 0xFFFF | ||
38 | #define RGB_565_MIN 0x0000 | ||
39 | |||
40 | struct test_t | ||
41 | { | ||
42 | char name[256]; | ||
43 | uint32_t src_color; | ||
44 | uint16_t dst_color; | ||
45 | size_t count; | ||
46 | }; | ||
47 | |||
48 | struct test_t tests[] = | ||
49 | { | ||
50 | {"Count 0", 0, 0, 0}, | ||
51 | {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1}, | ||
52 | {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2}, | ||
53 | {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3}, | ||
54 | {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4}, | ||
55 | {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1}, | ||
56 | {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2}, | ||
57 | {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3}, | ||
58 | {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4}, | ||
59 | {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5}, | ||
60 | {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10} | ||
61 | |||
62 | }; | ||
63 | |||
64 | void scanline_t32cb16blend_mips(uint16_t*, uint32_t*, size_t); | ||
65 | void scanline_t32cb16blend_c(uint16_t * dst, uint32_t* src, size_t count) | ||
66 | { | ||
67 | while (count--) | ||
68 | { | ||
69 | uint16_t d = *dst; | ||
70 | uint32_t s = *src++; | ||
71 | int dstR = (d>>11)&0x1f; | ||
72 | int dstG = (d>>5)&0x3f; | ||
73 | int dstB = (d)&0x1f; | ||
74 | int srcR = (s >> ( 3))&0x1F; | ||
75 | int srcG = (s >> ( 8+2))&0x3F; | ||
76 | int srcB = (s >> (16+3))&0x1F; | ||
77 | int srcAlpha = (s>>24) & 0xFF; | ||
78 | |||
79 | |||
80 | int f = 0x100 - (srcAlpha + ((srcAlpha>>7) & 0x1)); | ||
81 | srcR += (f*dstR)>>8; | ||
82 | srcG += (f*dstG)>>8; | ||
83 | srcB += (f*dstB)>>8; | ||
84 | // srcR = srcR > 0x1F? 0x1F: srcR; | ||
85 | // srcG = srcG > 0x3F? 0x3F: srcG; | ||
86 | // srcB = srcB > 0x1F? 0x1F: srcB; | ||
87 | *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | void scanline_t32cb16blend_test() | ||
92 | { | ||
93 | uint16_t dst_c[16], dst_asm[16]; | ||
94 | uint32_t src[16]; | ||
95 | uint32_t i; | ||
96 | uint32_t j; | ||
97 | |||
98 | for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i) | ||
99 | { | ||
100 | struct test_t test = tests[i]; | ||
101 | |||
102 | printf("Testing - %s:",test.name); | ||
103 | |||
104 | memset(dst_c, 0, sizeof(dst_c)); | ||
105 | memset(dst_asm, 0, sizeof(dst_asm)); | ||
106 | |||
107 | for(j = 0; j < test.count; ++j) | ||
108 | { | ||
109 | dst_c[j] = test.dst_color; | ||
110 | dst_asm[j] = test.dst_color; | ||
111 | src[j] = test.src_color; | ||
112 | } | ||
113 | |||
114 | scanline_t32cb16blend_c(dst_c,src,test.count); | ||
115 | scanline_t32cb16blend_mips(dst_asm,src,test.count); | ||
116 | |||
117 | |||
118 | if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0) | ||
119 | printf("Passed\n"); | ||
120 | else | ||
121 | printf("Failed\n"); | ||
122 | |||
123 | for(j = 0; j < test.count; ++j) | ||
124 | { | ||
125 | printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]); | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | |||
130 | int main() | ||
131 | { | ||
132 | scanline_t32cb16blend_test(); | ||
133 | return 0; | ||
134 | } | ||
diff --git a/libpixelflinger/tests/arch-mips64/Android.mk b/libpixelflinger/tests/arch-mips64/Android.mk new file mode 100644 index 000000000..3b1c64ec2 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/Android.mk | |||
@@ -0,0 +1,3 @@ | |||
1 | ifeq ($(TARGET_ARCH),mips64) | ||
2 | include $(all-subdir-makefiles) | ||
3 | endif | ||
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.mk b/libpixelflinger/tests/arch-mips64/assembler/Android.mk new file mode 100644 index 000000000..469996126 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/assembler/Android.mk | |||
@@ -0,0 +1,21 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | mips64_assembler_test.cpp\ | ||
6 | asm_mips_test_jacket.S | ||
7 | |||
8 | LOCAL_SHARED_LIBRARIES := \ | ||
9 | libcutils \ | ||
10 | libpixelflinger | ||
11 | |||
12 | LOCAL_C_INCLUDES := \ | ||
13 | $(LOCAL_PATH)/../../.. | ||
14 | |||
15 | LOCAL_MODULE:= test-pixelflinger-mips64-assembler-test | ||
16 | |||
17 | LOCAL_MODULE_TAGS := tests | ||
18 | |||
19 | LOCAL_MULTILIB := 64 | ||
20 | |||
21 | include $(BUILD_NATIVE_TEST) | ||
diff --git a/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S new file mode 100644 index 000000000..8a7f74202 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/assembler/asm_mips_test_jacket.S | |||
@@ -0,0 +1,93 @@ | |||
1 | # /* | ||
2 | # * Copyright (C) 2015 The Android Open Source Project | ||
3 | # * All rights reserved. | ||
4 | # * | ||
5 | # * Redistribution and use in source and binary forms, with or without | ||
6 | # * modification, are permitted provided that the following conditions | ||
7 | # * are met: | ||
8 | # * * Redistributions of source code must retain the above copyright | ||
9 | # * notice, this list of conditions and the following disclaimer. | ||
10 | # * * Redistributions in binary form must reproduce the above copyright | ||
11 | # * notice, this list of conditions and the following disclaimer in | ||
12 | # * the documentation and/or other materials provided with the | ||
13 | # * distribution. | ||
14 | # * | ||
15 | # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | # * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | # * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | # * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | # * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | # * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | # * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | # * SUCH DAMAGE. | ||
27 | # */ | ||
28 | |||
29 | .text | ||
30 | .align 8 | ||
31 | |||
32 | .global asm_mips_test_jacket | ||
33 | |||
34 | # // Set the register | ||
35 | # // Calls the asm function | ||
36 | # // Reads the register values to output register | ||
37 | |||
38 | # // Parameters | ||
39 | # // a0 - Function to jump | ||
40 | # // a1 - register values array | ||
41 | # // a2 - flag values array | ||
42 | asm_mips_test_jacket: | ||
43 | # // Save registers to stack | ||
44 | daddiu $sp, $sp, -96 | ||
45 | sd $s0, 64($sp) | ||
46 | sd $s1, 72($sp) | ||
47 | sd $s2, 80($sp) | ||
48 | sd $ra, 88($sp) | ||
49 | |||
50 | move $s0, $a0 | ||
51 | move $s1, $a1 | ||
52 | move $s2, $a2 | ||
53 | |||
54 | ld $v0, 16($s1) | ||
55 | ld $v1, 24($s1) | ||
56 | ld $a0, 32($s1) | ||
57 | ld $a1, 40($s1) | ||
58 | ld $a2, 48($s1) | ||
59 | ld $a3, 56($s1) | ||
60 | ld $a4, 64($s1) | ||
61 | ld $a5, 72($s1) | ||
62 | ld $a6, 80($s1) | ||
63 | ld $a7, 88($s1) | ||
64 | ld $t0, 96($s1) | ||
65 | ld $t1, 104($s1) | ||
66 | ld $t2, 112($s1) | ||
67 | ld $t3, 120($s1) | ||
68 | |||
69 | jal $s0 | ||
70 | |||
71 | sd $v0, 16($s1) | ||
72 | sd $v1, 24($s1) | ||
73 | sd $a0, 32($s1) | ||
74 | sd $a1, 40($s1) | ||
75 | sd $a2, 48($s1) | ||
76 | sd $a3, 56($s1) | ||
77 | sd $a4, 64($s1) | ||
78 | sd $a5, 72($s1) | ||
79 | sd $a6, 80($s1) | ||
80 | sd $a7, 88($s1) | ||
81 | sd $t0, 96($s1) | ||
82 | sd $t1, 104($s1) | ||
83 | sd $t2, 112($s1) | ||
84 | sd $t3, 120($s1) | ||
85 | |||
86 | ld $s0, 64($sp) | ||
87 | ld $s1, 72($sp) | ||
88 | ld $s2, 80($sp) | ||
89 | ld $ra, 88($sp) | ||
90 | |||
91 | daddiu $sp, $sp, 96 | ||
92 | |||
93 | j $ra | ||
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp new file mode 100644 index 000000000..2b25223de --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp | |||
@@ -0,0 +1,644 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 The Android Open Source Project | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in | ||
12 | * the documentation and/or other materials provided with the | ||
13 | * distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | * SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | #include <stdio.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <string.h> | ||
32 | #include <unistd.h> | ||
33 | #include <errno.h> | ||
34 | |||
35 | #include <sys/mman.h> | ||
36 | #include <cutils/ashmem.h> | ||
37 | #include <cutils/atomic.h> | ||
38 | #include <cutils/log.h> | ||
39 | |||
40 | #define __STDC_FORMAT_MACROS | ||
41 | #include <inttypes.h> | ||
42 | |||
43 | #include "codeflinger/ARMAssemblerInterface.h" | ||
44 | #include "codeflinger/MIPS64Assembler.h" | ||
45 | using namespace android; | ||
46 | |||
47 | #define TESTS_DATAOP_ENABLE 1 | ||
48 | #define TESTS_DATATRANSFER_ENABLE 1 | ||
49 | #define ASSEMBLY_SCRATCH_SIZE 4096 | ||
50 | |||
51 | void *instrMem; | ||
52 | uint32_t instrMemSize = 128 * 1024; | ||
53 | char dataMem[8192]; | ||
54 | |||
55 | typedef void (*asm_function_t)(); | ||
56 | extern "C" void asm_mips_test_jacket(asm_function_t function, | ||
57 | int64_t regs[], int32_t flags[]); | ||
58 | |||
59 | #define MAX_32BIT (uint32_t)(((uint64_t)1 << 32) - 1) | ||
60 | #define MAX_64BIT ((uint64_t)0xFFFFFFFFFFFFFFFF) | ||
61 | const uint32_t NA = 0; | ||
62 | const uint32_t NUM_REGS = 32; | ||
63 | const uint32_t NUM_FLAGS = 16; | ||
64 | |||
65 | enum instr_t | ||
66 | { | ||
67 | INSTR_ADD, | ||
68 | INSTR_SUB, | ||
69 | INSTR_AND, | ||
70 | INSTR_ORR, | ||
71 | INSTR_RSB, | ||
72 | INSTR_BIC, | ||
73 | INSTR_CMP, | ||
74 | INSTR_MOV, | ||
75 | INSTR_MVN, | ||
76 | INSTR_MUL, | ||
77 | INSTR_MLA, | ||
78 | INSTR_SMULBB, | ||
79 | INSTR_SMULBT, | ||
80 | INSTR_SMULTB, | ||
81 | INSTR_SMULTT, | ||
82 | INSTR_SMULWB, | ||
83 | INSTR_SMULWT, | ||
84 | INSTR_SMLABB, | ||
85 | INSTR_UXTB16, | ||
86 | INSTR_UBFX, | ||
87 | INSTR_ADDR_ADD, | ||
88 | INSTR_ADDR_SUB, | ||
89 | INSTR_LDR, | ||
90 | INSTR_LDRB, | ||
91 | INSTR_LDRH, | ||
92 | INSTR_ADDR_LDR, | ||
93 | INSTR_LDM, | ||
94 | INSTR_STR, | ||
95 | INSTR_STRB, | ||
96 | INSTR_STRH, | ||
97 | INSTR_ADDR_STR, | ||
98 | INSTR_STM | ||
99 | }; | ||
100 | |||
101 | enum shift_t | ||
102 | { | ||
103 | SHIFT_LSL, | ||
104 | SHIFT_LSR, | ||
105 | SHIFT_ASR, | ||
106 | SHIFT_ROR, | ||
107 | SHIFT_NONE | ||
108 | }; | ||
109 | |||
110 | enum offset_t | ||
111 | { | ||
112 | REG_SCALE_OFFSET, | ||
113 | REG_OFFSET, | ||
114 | IMM8_OFFSET, | ||
115 | IMM12_OFFSET, | ||
116 | NO_OFFSET | ||
117 | }; | ||
118 | |||
119 | enum cond_t | ||
120 | { | ||
121 | EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV, | ||
122 | HS = CS, | ||
123 | LO = CC | ||
124 | }; | ||
125 | |||
126 | const char * cc_code[] = | ||
127 | { | ||
128 | "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", | ||
129 | "HI", "LS","GE","LT", "GT", "LE", "AL", "NV" | ||
130 | }; | ||
131 | |||
132 | struct condTest_t | ||
133 | { | ||
134 | int mode; | ||
135 | int32_t Rcond1; | ||
136 | int32_t Rcond2; | ||
137 | uint64_t Rcond1Value; | ||
138 | uint64_t Rcond2Value; | ||
139 | }; | ||
140 | |||
141 | |||
142 | struct dataOpTest_t | ||
143 | { | ||
144 | uint32_t id; | ||
145 | instr_t op; | ||
146 | condTest_t preCond; | ||
147 | cond_t cond; | ||
148 | bool setFlags; | ||
149 | uint64_t RnValue; | ||
150 | uint64_t RsValue; | ||
151 | bool immediate; | ||
152 | uint32_t immValue; | ||
153 | uint64_t RmValue; | ||
154 | uint32_t shiftMode; | ||
155 | uint32_t shiftAmount; | ||
156 | uint64_t RdValue; | ||
157 | bool checkRd; | ||
158 | uint64_t postRdValue; | ||
159 | }; | ||
160 | |||
161 | struct dataTransferTest_t | ||
162 | { | ||
163 | uint32_t id; | ||
164 | instr_t op; | ||
165 | uint32_t preFlag; | ||
166 | cond_t cond; | ||
167 | bool setMem; | ||
168 | uint64_t memOffset; | ||
169 | uint64_t memValue; | ||
170 | uint64_t RnValue; | ||
171 | offset_t offsetType; | ||
172 | uint64_t RmValue; | ||
173 | uint32_t immValue; | ||
174 | bool writeBack; | ||
175 | bool preIndex; | ||
176 | bool postIndex; | ||
177 | uint64_t RdValue; | ||
178 | uint64_t postRdValue; | ||
179 | uint64_t postRnValue; | ||
180 | bool checkMem; | ||
181 | uint64_t postMemOffset; | ||
182 | uint32_t postMemLength; | ||
183 | uint64_t postMemValue; | ||
184 | }; | ||
185 | |||
186 | |||
187 | dataOpTest_t dataOpTests [] = | ||
188 | { | ||
189 | {0xA000,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0}, | ||
190 | {0xA001,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,MAX_64BIT}, | ||
191 | {0xA002,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,NA,NA,NA,1,0}, | ||
192 | {0xA003,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT-1,NA,NA,NA,1,MAX_64BIT}, | ||
193 | {0xA004,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL, 0,NA,1,0}, | ||
194 | {0xA005,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001}, | ||
195 | {0xA006,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,2}, | ||
196 | {0xA007,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,2}, | ||
197 | {0xA008,INSTR_ADD,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1}, | ||
198 | {0xA009,INSTR_ADD,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0}, | ||
199 | {0xA010,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,0,0,0,NA,1,1}, | ||
200 | {0xA011,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,0,0,0,NA,1,0}, | ||
201 | {0xA012,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,1}, | ||
202 | {0xA013,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,0}, | ||
203 | {0xA014,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,1}, | ||
204 | {0xA015,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0}, | ||
205 | {0xA016,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1}, | ||
206 | {0xA017,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1}, | ||
207 | {0xA018,INSTR_AND,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,0}, | ||
208 | {0xA019,INSTR_AND,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_ASR,31,NA,1,1}, | ||
209 | {0xA020,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,1,MAX_32BIT,0,0,0,NA,1,MAX_64BIT}, | ||
210 | {0xA021,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,1,MAX_32BIT-1,0,0,0,NA,1,MAX_64BIT-1}, | ||
211 | {0xA022,INSTR_ORR,{0,0,0,0,0},AL,0,3,NA,0,0,MAX_32BIT,0,0,NA,1,MAX_64BIT}, | ||
212 | {0xA023,INSTR_ORR,{0,0,0,0,0},AL,0,2,NA,0,0,MAX_32BIT-1,0,0,NA,1,MAX_64BIT-1}, | ||
213 | {0xA024,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,0,NA,1,MAX_64BIT}, | ||
214 | {0xA025,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000001}, | ||
215 | {0xA026,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,3,SHIFT_LSR,1,NA,1,1}, | ||
216 | {0xA027,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1}, | ||
217 | {0xA028,INSTR_ORR,{0,0,0,0,0},AL,0,0,NA,0,0,3,SHIFT_ASR,1,NA,1,1}, | ||
218 | {0xA029,INSTR_ORR,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,MAX_64BIT}, | ||
219 | {0xA030,INSTR_CMP,{0,0,0,0,0},AL,1,0x10000,NA,1,0x10000,0,0,0,NA,0,0}, | ||
220 | {0xA031,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x10000,0,0,0x10000,0,0,NA,1,0}, | ||
221 | {0xA032,INSTR_MUL,{0,0,0,0,0},AL,0,0,0x1000,0,0,0x10000,0,0,NA,1,0x10000000}, | ||
222 | {0xA033,INSTR_MUL,{0,0,0,0,0},AL,0,0,MAX_32BIT,0,0,1,0,0,NA,1,MAX_64BIT}, | ||
223 | {0xA034,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x10000,0,0,0x10000,0,0,NA,1,0x10000}, | ||
224 | {0xA035,INSTR_MLA,{0,0,0,0,0},AL,0,0x10000,0x1000,0,0,0x10000,0,0,NA,1,0x10010000}, | ||
225 | {0xA036,INSTR_SUB,{1,R_v1,R_a6,2,4},MI,0,2,NA,0,NA,1,NA,NA,2,1,1}, | ||
226 | {0xA037,INSTR_SUB,{2,R_v1,R_a6,2,0},MI,0,2,NA,0,NA,1,NA,NA,2,1,2}, | ||
227 | {0xA038,INSTR_SUB,{1,R_v1,R_a6,4,2},GE,0,2,NA,1,1,NA,NA,NA,2,1,1}, | ||
228 | {0xA039,INSTR_SUB,{1,R_a5,R_a6,2,7},GE,0,2,NA,1,1,NA,NA,NA,2,1,2}, | ||
229 | {0xA040,INSTR_SUB,{1,R_a5,R_a6,1,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,1}, | ||
230 | {0xA041,INSTR_SUB,{1,R_a5,R_a6,0,1},HS,0,2,NA,1,1,NA,NA,NA,2,1,2}, | ||
231 | {0xA042,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1<< 16,0,0,0,NA,1,(uint64_t)(1 -(1<<16))}, | ||
232 | {0xA043,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,0,0,0,NA,1,MAX_64BIT-1}, | ||
233 | {0xA044,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,1,1,0,0,0,NA,1,0}, | ||
234 | {0xA045,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(uint64_t)(1 -(1<<16))}, | ||
235 | {0xA046,INSTR_SUB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,MAX_64BIT-1}, | ||
236 | {0xA047,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0}, | ||
237 | {0xA048,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(uint64_t)(1 -(1<<16))}, | ||
238 | {0xA049,INSTR_SUB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT,SHIFT_LSL,31,NA,1,1}, | ||
239 | {0xA050,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0}, | ||
240 | {0xA051,INSTR_SUB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0}, | ||
241 | {0xA052,INSTR_RSB,{1,R_a5,R_a6,4,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,(uint64_t)-2}, | ||
242 | {0xA053,INSTR_RSB,{1,R_a5,R_a6,-1,1},GE,0,2,NA,1,0,NA,NA,NA,2,1,2}, | ||
243 | {0xA054,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1<<16,NA,NA,NA,NA,1,(1<<16)-1}, | ||
244 | {0xA055,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,1,1,NA,NA,NA,NA,1,(uint64_t)(1-MAX_64BIT)}, | ||
245 | {0xA056,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,1,1,NA,NA,NA,NA,1,0}, | ||
246 | {0xA057,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1<<16,0,0,NA,1,(1<<16)-1}, | ||
247 | {0xA058,INSTR_RSB,{0,0,0,0,0},AL,0,MAX_32BIT,NA,0,NA,1,0,0,NA,1,(uint64_t)(1-MAX_64BIT)}, | ||
248 | {0xA059,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,0,0,NA,1,0}, | ||
249 | {0xA060,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,1,SHIFT_LSL,16,NA,1,(1<<16)-1}, | ||
250 | {0xA061,INSTR_RSB,{0,0,0,0,0},AL,0,0x80000001,NA,0,NA,MAX_32BIT ,SHIFT_LSL,31,NA,1,(uint64_t)(-1)}, | ||
251 | {0xA062,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,3,SHIFT_LSR,1,NA,1,0}, | ||
252 | {0xA063,INSTR_RSB,{0,0,0,0,0},AL,0,1,NA,0,NA,MAX_32BIT,SHIFT_LSR,31,NA,1,0}, | ||
253 | {0xA064,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,1,0x80000001,NA,NA,NA,NA,1,0xFFFFFFFF80000001}, | ||
254 | {0xA065,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,0,0,NA,1,0xFFFFFFFF80000001}, | ||
255 | {0xA066,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,NA,1,MAX_64BIT-1}, | ||
256 | {0xA067,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,NA,1,0xFFFFFFFF80000000}, | ||
257 | {0xA068,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_LSR,1,NA,1,1}, | ||
258 | {0xA069,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSR,31,NA,1,1}, | ||
259 | {0xA070,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1}, | ||
260 | {0xA071,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,MAX_64BIT ,SHIFT_ASR,31,NA,1,MAX_64BIT}, | ||
261 | {0xA072,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,3,SHIFT_ROR,1,NA,1,0xFFFFFFFF80000001}, | ||
262 | {0xA073,INSTR_MOV,{0,0,0,0,0},AL,0,NA,NA,0,0,0x80000001,SHIFT_ROR,31,NA,1,3}, | ||
263 | {0xA074,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,MAX_64BIT -1,SHIFT_ASR,1,NA,1,MAX_64BIT}, | ||
264 | {0xA075,INSTR_MOV,{0,0,0,0,0},AL,1,NA,NA,0,0,3,SHIFT_ASR,1,NA,1,1}, | ||
265 | {0xA076,INSTR_MOV,{2,R_a5,R_a6,6,8},MI,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2}, | ||
266 | {0xA077,INSTR_MOV,{2,R_a5,R_a6,-4,-8},MI,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001}, | ||
267 | {0xA078,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2}, | ||
268 | {0xA079,INSTR_MOV,{1,R_a5,R_a6,-1,1},LT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001}, | ||
269 | {0xA080,INSTR_MOV,{1,R_a5,R_a6,-1,-5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1}, | ||
270 | {0xA081,INSTR_MOV,{1,R_a5,R_a6,5,5},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000}, | ||
271 | {0xA082,INSTR_MOV,{1,R_a5,R_a6,-1,1},GE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,2}, | ||
272 | {0xA083,INSTR_MOV,{1,R_a5,R_a6,4,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2}, | ||
273 | {0xA084,INSTR_MOV,{1,R_a5,R_a6,-1,-1},LE,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001}, | ||
274 | {0xA085,INSTR_MOV,{1,R_a5,R_a6,-1,1},LE,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,31,2,1,0xFFFFFFFF80000000}, | ||
275 | {0xA086,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2}, | ||
276 | {0xA087,INSTR_MOV,{1,R_a5,R_a6,-1,-3},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001}, | ||
277 | {0xA088,INSTR_MOV,{1,R_a5,R_a6,-1,0},GT,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2}, | ||
278 | {0xA089,INSTR_MOV,{1,R_a5,R_a6,-1,-1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2}, | ||
279 | {0xA090,INSTR_MOV,{1,R_a5,R_a6,6,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,0xFFFFFFFF80000001}, | ||
280 | {0xA091,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,0x80000001,0,0,2,1,2}, | ||
281 | {0xA092,INSTR_MOV,{1,R_a5,R_a6,1,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,2}, | ||
282 | {0xA093,INSTR_MOV,{1,R_a5,R_a6,4,1},GT,0,NA,NA,0,0,MAX_32BIT,SHIFT_LSL,1,2,1,MAX_64BIT-1}, | ||
283 | {0xA094,INSTR_MOV,{1,R_a5,R_a6,-1,1},GT,0,NA,NA,0,0,MAX_32BIT ,SHIFT_LSL,1,2,1,2}, | ||
284 | {0xA095,INSTR_MOV,{1,R_a5,R_a6,1,-1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,2}, | ||
285 | {0xA096,INSTR_MOV,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,0x80000001,NA,NA,NA,2,1,0xFFFFFFFF80000001}, | ||
286 | {0xA097,INSTR_MVN,{1,R_a5,R_a6,1,4},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,2}, | ||
287 | {0xA098,INSTR_MVN,{1,R_a5,R_a6,-1,1},HS,0,NA,NA,1,MAX_32BIT-1,NA,NA,NA,2,1,1}, | ||
288 | {0xA099,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,1,0,NA,NA,NA,2,1,MAX_64BIT}, | ||
289 | {0xA100,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,MAX_32BIT-1,NA,0,2,1,1}, | ||
290 | {0xA101,INSTR_MVN,{0,0,0,0,0},AL,0,NA,NA,0,NA,0x80000001,NA,0,2,1,0x7FFFFFFE}, | ||
291 | {0xA102,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT,NA,NA,NA,NA,1,0}, | ||
292 | {0xA103,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,1,MAX_32BIT-1,NA,NA,NA,NA,1,1}, | ||
293 | {0xA104,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT,0,0,NA,1,0}, | ||
294 | {0xA105,INSTR_BIC,{0,0,0,0,0},AL,0,1,NA,0,0,MAX_32BIT-1,0,0,NA,1,1}, | ||
295 | {0xA106,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,3,SHIFT_ASR,1,NA,1,0xF0}, | ||
296 | {0xA107,INSTR_BIC,{0,0,0,0,0},AL,0,0xF0,NA,0,0,MAX_64BIT,SHIFT_ASR,31,NA,1,0}, | ||
297 | {0xA108,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
298 | {0xA109,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF}, | ||
299 | {0xA110,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
300 | {0xA111,INSTR_SMULBB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1}, | ||
301 | {0xA112,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
302 | {0xA113,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00000FFF}, | ||
303 | {0xA114,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
304 | {0xA115,INSTR_SMULBT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFABCDFFFF,NA,NA,NA,1,1}, | ||
305 | {0xA116,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
306 | {0xA117,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF}, | ||
307 | {0xA118,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
308 | {0xA119,INSTR_SMULTB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1}, | ||
309 | {0xA120,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
310 | {0xA121,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF}, | ||
311 | {0xA122,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
312 | {0xA123,INSTR_SMULTT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,1}, | ||
313 | {0xA124,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE}, | ||
314 | {0xA125,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF}, | ||
315 | {0xA126,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
316 | {0xA127,INSTR_SMULWB,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0}, | ||
317 | {0xA128,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0x000000000001ABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE}, | ||
318 | {0xA129,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0x000000000FFFABCD,NA,NA,NA,1,0x00000FFF}, | ||
319 | {0xA130,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0x000000000001ABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0xFFFFFFFFFFFFFFFF}, | ||
320 | {0xA131,INSTR_SMULWT,{0,0,0,0,0},AL,0,NA,0xFFFFFFFFFFFFABCD,0,NA,0xFFFFFFFFFFFFABCD,NA,NA,NA,1,0}, | ||
321 | {0xA132,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCDFFFF,0,NA,0xFFFFFFFFABCD0001,NA,NA,NA,1,0}, | ||
322 | {0xA133,INSTR_SMLABB,{0,0,0,0,0},AL,0,1,0xFFFFFFFFABCD0001,0,NA,0xFFFFFFFFABCD0FFF,NA,NA,NA,1,0x00001000}, | ||
323 | {0xA134,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCD0001,0,NA,0xABCDFFFF,NA,NA,NA,1,0xFFFFFFFFFFFFFFFE}, | ||
324 | {0xA135,INSTR_SMLABB,{0,0,0,0,0},AL,0,0xFFFFFFFFFFFFFFFF,0xFFFFFFFFABCDFFFF,0,NA,0xABCDFFFF,NA,NA,NA,1,0}, | ||
325 | {0xA136,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,0,NA,1,0x00CD0001}, | ||
326 | {0xA137,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,1,NA,1,0x00AB00EF}, | ||
327 | {0xA138,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,2,NA,1,0x000100CD}, | ||
328 | {0xA139,INSTR_UXTB16,{0,0,0,0,0},AL,0,NA,NA,0,NA,0xABCDEF01,SHIFT_ROR,3,NA,1,0x00EF00AB}, | ||
329 | {0xA140,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,SHIFT_LSL,1,NA,1,0xD00000001}, | ||
330 | {0xA141,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0x01,NA,0,NA,0x1,SHIFT_LSL,2,NA,1,0x5}, | ||
331 | {0xA142,INSTR_ADDR_ADD,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x1,NA,0,NA,1,0xD00000000}, | ||
332 | {0xA143,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xD00000001,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,0xCFFFFFFFF}, | ||
333 | {0xA144,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,0xCFFFFFFFF,NA,0,NA,0x020000,SHIFT_LSR,15,NA,1,0xCFFFFFFFB}, | ||
334 | {0xA145,INSTR_ADDR_SUB,{0,0,0,0,0},AL,0,3,NA,0,NA,0x010000,SHIFT_LSR,15,NA,1,1}, | ||
335 | }; | ||
336 | |||
337 | dataTransferTest_t dataTransferTests [] = | ||
338 | { | ||
339 | {0xB000,INSTR_LDR,AL,AL,1,24,0xABCDEF0123456789,0,REG_SCALE_OFFSET,24,NA,NA,NA,NA,NA,0x23456789,0,0,NA,NA,NA}, | ||
340 | {0xB001,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,IMM12_OFFSET,NA,4,1,0,1,NA,0x23456789,4,0,NA,NA,NA}, | ||
341 | {0xB002,INSTR_LDR,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x23456789,0,0,NA,NA,NA}, | ||
342 | {0xB003,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,REG_SCALE_OFFSET,4064,NA,NA,NA,NA,NA,0x89,0,0,NA,NA,NA}, | ||
343 | {0xB004,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,0,0,1,0,NA,0x67,4065,0,NA,NA,NA}, | ||
344 | {0xB005,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,0,1,0,NA,0x45,4065,0,NA,NA,NA}, | ||
345 | {0xB006,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,2,0,1,0,NA,0x23,4065,0,NA,NA,NA}, | ||
346 | {0xB007,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,4065,IMM12_OFFSET,NA,1,1,0,1,NA,0x67,4066,0,NA,NA,NA}, | ||
347 | {0xB008,INSTR_LDRB,AL,AL,1,4064,0xABCDEF0123456789,0,NO_OFFSET,NA,NA,0,0,0,NA,0x89,0,0,NA,NA,NA}, | ||
348 | {0xB009,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,IMM8_OFFSET,NA,2,1,0,1,NA,0x6789,2,0,NA,NA,NA}, | ||
349 | {0xB010,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4064,0,0,1,0,NA,0x6789,0,0,NA,NA,NA}, | ||
350 | {0xB011,INSTR_LDRH,AL,AL,1,4064,0xABCDEF0123456789,0,REG_OFFSET,4066,0,0,1,0,NA,0x2345,0,0,NA,NA,NA}, | ||
351 | {0xB012,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,0,NO_OFFSET,NA,0,0,0,0,NA,0x6789,0,0,NA,NA,NA}, | ||
352 | {0xB013,INSTR_LDRH,AL,AL,1,0,0xABCDEF0123456789,2,NO_OFFSET,NA,0,0,0,0,NA,0x2345,2,0,NA,NA,NA}, | ||
353 | {0xB014,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,8,1,2,8,0xDEAD23456789BEEF}, | ||
354 | {0xB015,INSTR_STR,AL,AL,1,2,0xDEADBEEFDEADBEEF,4,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4,1,2,8,0xDEAD23456789BEEF}, | ||
355 | {0xB016,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,0,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF}, | ||
356 | {0xB017,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,1,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDE89BEEF}, | ||
357 | {0xB018,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,2,0,1,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEF89ADBEEF}, | ||
358 | {0xB019,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,IMM12_OFFSET,NA,4,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,5,1,0,8,0xDEADBEEFDEAD89EF}, | ||
359 | {0xB020,INSTR_STRB,AL,AL,1,0,0xDEADBEEFDEADBEEF,1,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,1,1,0,8,0xDEADBEEFDEAD89EF}, | ||
360 | {0xB021,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,IMM8_OFFSET,NA,2,1,0,1,0xABCDEF0123456789,0xABCDEF0123456789,4072,1,4066,8,0xDEAD6789DEADBEEF}, | ||
361 | {0xB022,INSTR_STRH,AL,AL,1,4066,0xDEADBEEFDEADBEEF,4070,NO_OFFSET,NA,NA,0,0,0,0xABCDEF0123456789,0xABCDEF0123456789,4070,1,4066,8,0xDEAD6789DEADBEEF}, | ||
362 | }; | ||
363 | |||
364 | |||
365 | void flushcache() | ||
366 | { | ||
367 | const long base = long(instrMem); | ||
368 | const long curr = base + long(instrMemSize); | ||
369 | __builtin___clear_cache((char*)base, (char*)curr); | ||
370 | } | ||
371 | |||
372 | void dataOpTest(dataOpTest_t test, ArmToMips64Assembler *a64asm, uint32_t Rd = R_v1, | ||
373 | uint32_t Rn = R_t0, uint32_t Rm = R_t1, uint32_t Rs = R_t2) | ||
374 | { | ||
375 | int64_t regs[NUM_REGS] = {0}; | ||
376 | int32_t flags[NUM_FLAGS] = {0}; | ||
377 | int64_t savedRegs[NUM_REGS] = {0}; | ||
378 | uint32_t i; | ||
379 | uint32_t op2; | ||
380 | |||
381 | for(i = 0; i < NUM_REGS; ++i) | ||
382 | { | ||
383 | regs[i] = i; | ||
384 | } | ||
385 | |||
386 | regs[Rd] = test.RdValue; | ||
387 | regs[Rn] = test.RnValue; | ||
388 | regs[Rs] = test.RsValue; | ||
389 | a64asm->reset(); | ||
390 | if (test.preCond.mode) { | ||
391 | a64asm->set_condition(test.preCond.mode, test.preCond.Rcond1, test.preCond.Rcond2); | ||
392 | regs[test.preCond.Rcond1] = test.preCond.Rcond1Value; | ||
393 | regs[test.preCond.Rcond2] = test.preCond.Rcond2Value; | ||
394 | } | ||
395 | a64asm->prolog(); | ||
396 | if(test.immediate == true) | ||
397 | { | ||
398 | op2 = a64asm->imm(test.immValue); | ||
399 | } | ||
400 | else if(test.immediate == false && test.shiftAmount == 0) | ||
401 | { | ||
402 | op2 = Rm; | ||
403 | regs[Rm] = (int64_t)((int32_t)(test.RmValue)); | ||
404 | } | ||
405 | else | ||
406 | { | ||
407 | op2 = a64asm->reg_imm(Rm, test.shiftMode, test.shiftAmount); | ||
408 | regs[Rm] = (int64_t)((int32_t)(test.RmValue)); | ||
409 | } | ||
410 | switch(test.op) | ||
411 | { | ||
412 | case INSTR_ADD: a64asm->ADD(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
413 | case INSTR_SUB: a64asm->SUB(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
414 | case INSTR_RSB: a64asm->RSB(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
415 | case INSTR_AND: a64asm->AND(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
416 | case INSTR_ORR: a64asm->ORR(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
417 | case INSTR_BIC: a64asm->BIC(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
418 | case INSTR_MUL: a64asm->MUL(test.cond, test.setFlags, Rd,Rm,Rs); break; | ||
419 | case INSTR_MLA: a64asm->MLA(test.cond, test.setFlags, Rd,Rm,Rs,Rn); break; | ||
420 | case INSTR_CMP: a64asm->CMP(test.cond, Rn,op2); break; | ||
421 | case INSTR_MOV: a64asm->MOV(test.cond, test.setFlags,Rd,op2); break; | ||
422 | case INSTR_MVN: a64asm->MVN(test.cond, test.setFlags,Rd,op2); break; | ||
423 | case INSTR_SMULBB:a64asm->SMULBB(test.cond, Rd,Rm,Rs); break; | ||
424 | case INSTR_SMULBT:a64asm->SMULBT(test.cond, Rd,Rm,Rs); break; | ||
425 | case INSTR_SMULTB:a64asm->SMULTB(test.cond, Rd,Rm,Rs); break; | ||
426 | case INSTR_SMULTT:a64asm->SMULTT(test.cond, Rd,Rm,Rs); break; | ||
427 | case INSTR_SMULWB:a64asm->SMULWB(test.cond, Rd,Rm,Rs); break; | ||
428 | case INSTR_SMULWT:a64asm->SMULWT(test.cond, Rd,Rm,Rs); break; | ||
429 | case INSTR_SMLABB:a64asm->SMLABB(test.cond, Rd,Rm,Rs,Rn); break; | ||
430 | case INSTR_UXTB16:a64asm->UXTB16(test.cond, Rd,Rm,test.shiftAmount); break; | ||
431 | case INSTR_ADDR_ADD: a64asm->ADDR_ADD(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
432 | case INSTR_ADDR_SUB: a64asm->ADDR_SUB(test.cond, test.setFlags, Rd,Rn,op2); break; | ||
433 | default: printf("Error"); return; | ||
434 | } | ||
435 | a64asm->epilog(0); | ||
436 | a64asm->fix_branches(); | ||
437 | flushcache(); | ||
438 | |||
439 | asm_function_t asm_function = (asm_function_t)(instrMem); | ||
440 | |||
441 | for(i = 0; i < NUM_REGS; ++i) | ||
442 | savedRegs[i] = regs[i]; | ||
443 | |||
444 | asm_mips_test_jacket(asm_function, regs, flags); | ||
445 | |||
446 | /* Check if all regs except Rd is same */ | ||
447 | for(i = 0; i < NUM_REGS; ++i) | ||
448 | { | ||
449 | if((i == Rd) || i == 2) continue; | ||
450 | if(regs[i] != savedRegs[i]) | ||
451 | { | ||
452 | printf("Test %x failed Reg(%d) tampered Expected(0x%" PRIx64 ")," | ||
453 | "Actual(0x%" PRIx64 ") t\n", test.id, i, savedRegs[i], | ||
454 | regs[i]); | ||
455 | exit(0); | ||
456 | return; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if(test.checkRd == 1 && regs[Rd] != test.postRdValue) | ||
461 | { | ||
462 | printf("Test %x failed, Expected(%" PRIx64 "), Actual(%" PRIx64 ")\n", | ||
463 | test.id, test.postRdValue, regs[Rd]); | ||
464 | exit(0); | ||
465 | } | ||
466 | else | ||
467 | { | ||
468 | printf("Test %x passed\n", test.id); | ||
469 | } | ||
470 | } | ||
471 | |||
472 | |||
473 | void dataTransferTest(dataTransferTest_t test, ARMAssemblerInterface *a64asm, | ||
474 | uint32_t Rd = R_v1, uint32_t Rn = R_t0,uint32_t Rm = R_t1) | ||
475 | { | ||
476 | int64_t regs[NUM_REGS] = {0}; | ||
477 | int64_t savedRegs[NUM_REGS] = {0}; | ||
478 | int32_t flags[NUM_FLAGS] = {0}; | ||
479 | uint32_t i; | ||
480 | for(i = 0; i < NUM_REGS; ++i) | ||
481 | { | ||
482 | regs[i] = i; | ||
483 | } | ||
484 | |||
485 | uint32_t op2; | ||
486 | |||
487 | regs[Rd] = test.RdValue; | ||
488 | regs[Rn] = (uint64_t)(&dataMem[test.RnValue]); | ||
489 | regs[Rm] = test.RmValue; | ||
490 | flags[test.preFlag] = 1; | ||
491 | |||
492 | if(test.setMem == true) | ||
493 | { | ||
494 | unsigned char *mem = (unsigned char *)&dataMem[test.memOffset]; | ||
495 | uint64_t value = test.memValue; | ||
496 | for(int j = 0; j < 8; ++j) | ||
497 | { | ||
498 | mem[j] = value & 0x00FF; | ||
499 | value >>= 8; | ||
500 | } | ||
501 | } | ||
502 | a64asm->reset(); | ||
503 | a64asm->prolog(); | ||
504 | if(test.offsetType == REG_SCALE_OFFSET) | ||
505 | { | ||
506 | op2 = a64asm->reg_scale_pre(Rm); | ||
507 | } | ||
508 | else if(test.offsetType == REG_OFFSET) | ||
509 | { | ||
510 | op2 = a64asm->reg_pre(Rm); | ||
511 | } | ||
512 | else if(test.offsetType == IMM12_OFFSET && test.preIndex == true) | ||
513 | { | ||
514 | op2 = a64asm->immed12_pre(test.immValue, test.writeBack); | ||
515 | } | ||
516 | else if(test.offsetType == IMM12_OFFSET && test.postIndex == true) | ||
517 | { | ||
518 | op2 = a64asm->immed12_post(test.immValue); | ||
519 | } | ||
520 | else if(test.offsetType == IMM8_OFFSET && test.preIndex == true) | ||
521 | { | ||
522 | op2 = a64asm->immed8_pre(test.immValue, test.writeBack); | ||
523 | } | ||
524 | else if(test.offsetType == IMM8_OFFSET && test.postIndex == true) | ||
525 | { | ||
526 | op2 = a64asm->immed8_post(test.immValue); | ||
527 | } | ||
528 | else if(test.offsetType == NO_OFFSET) | ||
529 | { | ||
530 | op2 = a64asm->__immed12_pre(0); | ||
531 | } | ||
532 | else | ||
533 | { | ||
534 | printf("Error - Unknown offset\n"); return; | ||
535 | } | ||
536 | |||
537 | switch(test.op) | ||
538 | { | ||
539 | case INSTR_LDR: a64asm->LDR(test.cond, Rd,Rn,op2); break; | ||
540 | case INSTR_LDRB: a64asm->LDRB(test.cond, Rd,Rn,op2); break; | ||
541 | case INSTR_LDRH: a64asm->LDRH(test.cond, Rd,Rn,op2); break; | ||
542 | case INSTR_ADDR_LDR: a64asm->ADDR_LDR(test.cond, Rd,Rn,op2); break; | ||
543 | case INSTR_STR: a64asm->STR(test.cond, Rd,Rn,op2); break; | ||
544 | case INSTR_STRB: a64asm->STRB(test.cond, Rd,Rn,op2); break; | ||
545 | case INSTR_STRH: a64asm->STRH(test.cond, Rd,Rn,op2); break; | ||
546 | case INSTR_ADDR_STR: a64asm->ADDR_STR(test.cond, Rd,Rn,op2); break; | ||
547 | default: printf("Error"); return; | ||
548 | } | ||
549 | a64asm->epilog(0); | ||
550 | flushcache(); | ||
551 | |||
552 | asm_function_t asm_function = (asm_function_t)(instrMem); | ||
553 | |||
554 | for(i = 0; i < NUM_REGS; ++i) | ||
555 | savedRegs[i] = regs[i]; | ||
556 | |||
557 | asm_mips_test_jacket(asm_function, regs, flags); | ||
558 | |||
559 | /* Check if all regs except Rd/Rn are same */ | ||
560 | for(i = 0; i < NUM_REGS; ++i) | ||
561 | { | ||
562 | if(i == Rd || i == Rn || i == R_v0) continue; | ||
563 | |||
564 | if(regs[i] != savedRegs[i]) | ||
565 | { | ||
566 | printf("Test %x failed Reg(%d) tampered" | ||
567 | " Expected(0x%" PRIx64 "), Actual(0x%" PRIx64 ") t\n", | ||
568 | test.id, i, savedRegs[i], regs[i]); | ||
569 | return; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | if((uint64_t)regs[Rd] != test.postRdValue) | ||
574 | { | ||
575 | printf("Test %x failed, " | ||
576 | "Expected in Rd(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n", | ||
577 | test.id, test.postRdValue, regs[Rd]); | ||
578 | } | ||
579 | else if((uint64_t)regs[Rn] != (uint64_t)(&dataMem[test.postRnValue])) | ||
580 | { | ||
581 | printf("Test %x failed, " | ||
582 | "Expected in Rn(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n", | ||
583 | test.id, test.postRnValue, regs[Rn] - (uint64_t)dataMem); | ||
584 | } | ||
585 | else if(test.checkMem == true) | ||
586 | { | ||
587 | unsigned char *addr = (unsigned char *)&dataMem[test.postMemOffset]; | ||
588 | uint64_t value; | ||
589 | value = 0; | ||
590 | for(uint32_t j = 0; j < test.postMemLength; ++j) | ||
591 | value = (value << 8) | addr[test.postMemLength-j-1]; | ||
592 | if(value != test.postMemValue) | ||
593 | { | ||
594 | printf("Test %x failed, " | ||
595 | "Expected in Mem(0x%" PRIx64 "), Actual(0x%" PRIx64 ")\n", | ||
596 | test.id, test.postMemValue, value); | ||
597 | } | ||
598 | else | ||
599 | { | ||
600 | printf("Test %x passed\n", test.id); | ||
601 | } | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | printf("Test %x passed\n", test.id); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | int main(void) | ||
610 | { | ||
611 | uint32_t i; | ||
612 | |||
613 | /* Allocate memory to store instructions generated by ArmToArm64Assembler */ | ||
614 | { | ||
615 | int fd = ashmem_create_region("code cache", instrMemSize); | ||
616 | if(fd < 0) { | ||
617 | printf("IF < 0\n"); | ||
618 | printf("Creating code cache, ashmem_create_region " | ||
619 | "failed with error '%s'", strerror(errno)); | ||
620 | } | ||
621 | instrMem = mmap(NULL, instrMemSize, | ||
622 | PROT_READ | PROT_WRITE | PROT_EXEC, | ||
623 | MAP_PRIVATE, fd, 0); | ||
624 | } | ||
625 | |||
626 | ArmToMips64Assembler a64asm(instrMem); | ||
627 | |||
628 | if(TESTS_DATAOP_ENABLE) | ||
629 | { | ||
630 | printf("Running data processing tests\n"); | ||
631 | for(i = 0; i < sizeof(dataOpTests)/sizeof(dataOpTest_t); ++i) { | ||
632 | dataOpTest(dataOpTests[i], &a64asm); | ||
633 | } | ||
634 | } | ||
635 | |||
636 | if(TESTS_DATATRANSFER_ENABLE) | ||
637 | { | ||
638 | printf("Running data transfer tests\n"); | ||
639 | for(i = 0; i < sizeof(dataTransferTests)/sizeof(dataTransferTest_t); ++i) | ||
640 | dataTransferTest(dataTransferTests[i], &a64asm); | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk new file mode 100644 index 000000000..7d4177ecb --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk | |||
@@ -0,0 +1,18 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | col32cb16blend_test.c \ | ||
6 | ../../../arch-mips64/col32cb16blend.S | ||
7 | |||
8 | LOCAL_SHARED_LIBRARIES := | ||
9 | |||
10 | LOCAL_C_INCLUDES := | ||
11 | |||
12 | LOCAL_MODULE:= test-pixelflinger-mips64-col32cb16blend | ||
13 | |||
14 | LOCAL_MODULE_TAGS := tests | ||
15 | |||
16 | LOCAL_MULTILIB := 64 | ||
17 | |||
18 | include $(BUILD_NATIVE_TEST) | ||
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c new file mode 100644 index 000000000..066eab679 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/col32cb16blend/col32cb16blend_test.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 The Android Open Source Project | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in | ||
12 | * the documentation and/or other materials provided with the | ||
13 | * distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | * SUCH DAMAGE. | ||
27 | */ | ||
28 | |||
29 | #include <assert.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <stdio.h> | ||
32 | #include <string.h> | ||
33 | #include <inttypes.h> | ||
34 | |||
35 | |||
36 | #define ARGB_8888_MAX 0xFFFFFFFF | ||
37 | #define ARGB_8888_MIN 0x00000000 | ||
38 | #define RGB_565_MAX 0xFFFF | ||
39 | #define RGB_565_MIN 0x0000 | ||
40 | |||
41 | struct test_t | ||
42 | { | ||
43 | char name[256]; | ||
44 | uint32_t src_color; | ||
45 | uint16_t dst_color; | ||
46 | size_t count; | ||
47 | }; | ||
48 | |||
49 | struct test_t tests[] = | ||
50 | { | ||
51 | {"Count 1, Src=Max, Dst=Min", ARGB_8888_MAX, RGB_565_MIN, 1}, | ||
52 | {"Count 2, Src=Min, Dst=Max", ARGB_8888_MIN, RGB_565_MAX, 2}, | ||
53 | {"Count 3, Src=Max, Dst=Max", ARGB_8888_MAX, RGB_565_MAX, 3}, | ||
54 | {"Count 4, Src=Min, Dst=Min", ARGB_8888_MAX, RGB_565_MAX, 4}, | ||
55 | {"Count 1, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 1}, | ||
56 | {"Count 2, Src=Rand, Dst=Rand", 0xABCDEF12, 0x2345, 2}, | ||
57 | {"Count 3, Src=Rand, Dst=Rand", 0x11111111, 0xEDFE, 3}, | ||
58 | {"Count 4, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 4}, | ||
59 | {"Count 5, Src=Rand, Dst=Rand", 0xEFEFFEFE, 0xFACC, 5}, | ||
60 | {"Count 10, Src=Rand, Dst=Rand", 0x12345678, 0x9ABC, 10} | ||
61 | }; | ||
62 | |||
63 | void scanline_col32cb16blend_mips64(uint16_t *dst, uint32_t src, size_t count); | ||
64 | void scanline_col32cb16blend_c(uint16_t * dst, uint32_t src, size_t count) | ||
65 | { | ||
66 | uint32_t srcAlpha = (src>>24); | ||
67 | uint32_t f = 0x100 - (srcAlpha + (srcAlpha>>7)); | ||
68 | |||
69 | while (count--) | ||
70 | { | ||
71 | uint16_t d = *dst; | ||
72 | int dstR = (d>>11)&0x1f; | ||
73 | int dstG = (d>>5)&0x3f; | ||
74 | int dstB = (d)&0x1f; | ||
75 | int srcR = (src >> ( 3))&0x1F; | ||
76 | int srcG = (src >> ( 8+2))&0x3F; | ||
77 | int srcB = (src >> (16+3))&0x1F; | ||
78 | srcR += (f*dstR)>>8; | ||
79 | srcG += (f*dstG)>>8; | ||
80 | srcB += (f*dstB)>>8; | ||
81 | *dst++ = (uint16_t)((srcR<<11)|(srcG<<5)|srcB); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void scanline_col32cb16blend_test() | ||
86 | { | ||
87 | uint16_t dst_c[16], dst_asm[16]; | ||
88 | uint32_t i, j; | ||
89 | |||
90 | for(i = 0; i < sizeof(tests)/sizeof(struct test_t); ++i) | ||
91 | { | ||
92 | struct test_t test = tests[i]; | ||
93 | |||
94 | printf("Testing - %s:",test.name); | ||
95 | |||
96 | memset(dst_c, 0, sizeof(dst_c)); | ||
97 | memset(dst_asm, 0, sizeof(dst_asm)); | ||
98 | |||
99 | for(j = 0; j < test.count; ++j) | ||
100 | { | ||
101 | dst_c[j] = test.dst_color; | ||
102 | dst_asm[j] = test.dst_color; | ||
103 | } | ||
104 | |||
105 | |||
106 | scanline_col32cb16blend_c(dst_c, test.src_color, test.count); | ||
107 | scanline_col32cb16blend_mips64(dst_asm, test.src_color, test.count); | ||
108 | |||
109 | if(memcmp(dst_c, dst_asm, sizeof(dst_c)) == 0) | ||
110 | printf("Passed\n"); | ||
111 | else | ||
112 | printf("Failed\n"); | ||
113 | |||
114 | for(j = 0; j < test.count; ++j) | ||
115 | { | ||
116 | printf("dst_c[%d] = %x, dst_asm[%d] = %x \n", j, dst_c[j], j, dst_asm[j]); | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | |||
121 | int main() | ||
122 | { | ||
123 | scanline_col32cb16blend_test(); | ||
124 | return 0; | ||
125 | } | ||
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.mk b/libpixelflinger/tests/arch-mips64/disassembler/Android.mk new file mode 100644 index 000000000..4e72b5784 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/disassembler/Android.mk | |||
@@ -0,0 +1,16 @@ | |||
1 | LOCAL_PATH:= $(call my-dir) | ||
2 | include $(CLEAR_VARS) | ||
3 | |||
4 | LOCAL_SRC_FILES:= \ | ||
5 | mips64_disassembler_test.cpp \ | ||
6 | ../../../codeflinger/mips64_disassem.c | ||
7 | |||
8 | LOCAL_SHARED_LIBRARIES := | ||
9 | |||
10 | LOCAL_MODULE:= test-pixelflinger-mips64-disassembler-test | ||
11 | |||
12 | LOCAL_MODULE_TAGS := tests | ||
13 | |||
14 | LOCAL_MULTILIB := 64 | ||
15 | |||
16 | include $(BUILD_NATIVE_TEST) | ||
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp new file mode 100644 index 000000000..41f6f3ef9 --- /dev/null +++ b/libpixelflinger/tests/arch-mips64/disassembler/mips64_disassembler_test.cpp | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 The Android Open Source Project | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions | ||
7 | * are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in | ||
12 | * the documentation and/or other materials provided with the | ||
13 | * distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | ||
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
26 | * SUCH DAMAGE. | ||
27 | */ | ||
28 | #include <stdio.h> | ||
29 | #include <inttypes.h> | ||
30 | #include <string.h> | ||
31 | #include "../../../codeflinger/mips64_disassem.h" | ||
32 | |||
33 | //typedef uint64_t db_addr_t; | ||
34 | //db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_format); | ||
35 | |||
36 | struct test_table_entry_t | ||
37 | { | ||
38 | uint32_t code; | ||
39 | const char *instr; | ||
40 | }; | ||
41 | |||
42 | static test_table_entry_t test_table [] = | ||
43 | { | ||
44 | { 0x00011020, "add\tv0,zero,at" }, | ||
45 | { 0x00832820, "add\ta1,a0,v1" }, | ||
46 | { 0x00c74020, "add\ta4,a2,a3" }, | ||
47 | { 0x012a5820, "add\ta7,a5,a6" }, | ||
48 | { 0x258dffff, "addiu\tt1,t0,-1" }, | ||
49 | { 0x25cf0004, "addiu\tt3,t2,4" }, | ||
50 | { 0x02119021, "addu\ts2,s0,s1" }, | ||
51 | { 0x0274a821, "addu\ts5,s3,s4" }, | ||
52 | { 0x02d7c024, "and\tt8,s6,s7" }, | ||
53 | { 0x333aff00, "andi\tk0,t9,0xff00" }, | ||
54 | { 0x3f7cffff, "aui\tgp,k1,-1" }, | ||
55 | { 0x3c1dffff, "lui\tsp,0xffff" }, | ||
56 | { 0x00e04051, "clo\ta4,a3" }, | ||
57 | { 0x01205050, "clz\ta6,a5" }, | ||
58 | { 0x016c682c, "dadd\tt1,a7,t0" }, | ||
59 | { 0x65cf0008, "daddiu\tt3,t2,8" }, | ||
60 | { 0x0211902d, "daddu\ts2,s0,s1" }, | ||
61 | { 0x7e741403, "dext\ts4,s3,16,3" }, | ||
62 | { 0x7eb6f801, "dextm\ts6,s5,0,64" }, | ||
63 | { 0x7ef87c02, "dextu\tt8,s7,48,16" }, | ||
64 | { 0x7f3a8207, "dins\tk0,t9,8,9" }, | ||
65 | { 0x7f7c0005, "dinsm\tgp,k1,0,33" }, | ||
66 | { 0x7fbe0806, "dinsu\ts8,sp,32,2" }, | ||
67 | { 0x03e1102e, "dsub\tv0,ra,at" }, | ||
68 | { 0x0064282f, "dsubu\ta1,v1,a0" }, | ||
69 | { 0x7cc77a00, "ext\ta3,a2,8,16" }, | ||
70 | { 0x7d09fc04, "ins\ta5,a4,16,16" }, | ||
71 | { 0x00200009, "jr\tat" }, | ||
72 | { 0x00201009, "jalr\tv0,at" }, | ||
73 | { 0x0020f809, "jalr\tat" }, | ||
74 | { 0x8082fff0, "lb\tv0,-16(a0)" }, | ||
75 | { 0x916c0008, "lbu\tt0,8(a7)" }, | ||
76 | { 0xdfa3ffe8, "ld\tv1,-24(sp)" }, | ||
77 | { 0x84850080, "lh\ta1,128(a0)" }, | ||
78 | { 0x94c7ff80, "lhu\ta3,-128(a2)" }, | ||
79 | { 0x8d09000c, "lw\ta5,12(a4)" }, | ||
80 | { 0x9d4bfff4, "lwu\ta7,-12(a6)" }, | ||
81 | { 0x00620898, "mul\tat,v1,v0" }, | ||
82 | { 0x006208d8, "muh\tat,v1,v0" }, | ||
83 | { 0x00620899, "mulu\tat,v1,v0" }, | ||
84 | { 0x006208d9, "muhu\tat,v1,v0" }, | ||
85 | { 0x00000000, "nop" }, | ||
86 | { 0x02329827, "nor\ts3,s1,s2" }, | ||
87 | { 0x0295b025, "or\ts6,s4,s5" }, | ||
88 | { 0x36f0ff00, "ori\ts0,s7,0xff00" }, | ||
89 | { 0x7c03103b, "rdhwr\tv0,v1" }, | ||
90 | { 0x00242a02, "rotr\ta1,a0,8" }, | ||
91 | { 0x00c74046, "rotrv\ta4,a3,a2" }, | ||
92 | { 0xa12afff0, "sb\ta6,-16(a5)" }, | ||
93 | { 0xfd6c0100, "sd\tt0,256(a7)" }, | ||
94 | { 0x7c0d7420, "seb\tt2,t1" }, | ||
95 | { 0x7c0f8620, "seh\ts0,t3" }, | ||
96 | { 0x02329835, "seleqz\ts3,s1,s2" }, | ||
97 | { 0x0295b037, "selnez\ts6,s4,s5" }, | ||
98 | { 0xa6f84000, "sh\tt8,16384(s7)" }, | ||
99 | { 0x0019d100, "sll\tk0,t9,4" }, | ||
100 | { 0x037ce804, "sllv\tsp,gp,k1" }, | ||
101 | { 0x03df082a, "slt\tat,s8,ra" }, | ||
102 | { 0x28430007, "slti\tv1,v0,7" }, | ||
103 | { 0x2c850020, "sltiu\ta1,a0,32" }, | ||
104 | { 0x00c7402b, "sltu\ta4,a2,a3" }, | ||
105 | { 0x00095103, "sra\ta6,a5,4" }, | ||
106 | { 0x016c6807, "srav\tt1,t0,a7" }, | ||
107 | { 0x000e7a02, "srl\tt3,t2,8" }, | ||
108 | { 0x02119006, "srlv\ts2,s1,s0" }, | ||
109 | { 0x0274a822, "sub\ts5,s3,s4" }, | ||
110 | { 0x02d7c023, "subu\tt8,s6,s7" }, | ||
111 | { 0xaf3afffc, "sw\tk0,-4(t9)" }, | ||
112 | { 0x7c1be0a0, "wsbh\tgp,k1" }, | ||
113 | { 0x03bef826, "xor\tra,sp,s8" }, | ||
114 | { 0x3801ffff, "li\tat,0xffff" }, | ||
115 | { 0x3843ffff, "xori\tv1,v0,0xffff" }, | ||
116 | }; | ||
117 | |||
118 | struct test_branches_table_entry_t | ||
119 | { | ||
120 | uint32_t code; | ||
121 | const char *instr; | ||
122 | int16_t offset; | ||
123 | }; | ||
124 | |||
125 | static test_branches_table_entry_t test_branches_table [] = { | ||
126 | { 0x1000ffff, "b\t", 0xffff }, | ||
127 | { 0x13df0008, "beq\ts8,ra,", 0x8 }, | ||
128 | { 0x042100ff, "bgez\tat,", 0xff }, | ||
129 | { 0x1c40ff00, "bgtz\tv0,", 0xff00 }, | ||
130 | { 0x18605555, "blez\tv1,", 0x5555 }, | ||
131 | { 0x0480aaaa, "bltz\ta0,", 0xaaaa }, | ||
132 | { 0x14a68888, "bne\ta1,a2,", 0x8888 }, | ||
133 | }; | ||
134 | |||
135 | struct test_jump_table_entry_t | ||
136 | { | ||
137 | uint32_t code; | ||
138 | const char *instr; | ||
139 | int32_t offset; | ||
140 | }; | ||
141 | |||
142 | static test_jump_table_entry_t test_jump_table [] = { | ||
143 | { 0x0956ae66, "j\t", 0x156ae66 }, | ||
144 | { 0x0d56ae66, "jal\t", 0x156ae66 }, | ||
145 | }; | ||
146 | |||
147 | int main() | ||
148 | { | ||
149 | char instr[256]; | ||
150 | uint32_t failed = 0; | ||
151 | |||
152 | for(uint32_t i = 0; i < sizeof(test_table)/sizeof(test_table_entry_t); ++i) | ||
153 | { | ||
154 | test_table_entry_t *test; | ||
155 | test = &test_table[i]; | ||
156 | mips_disassem(&test->code, instr, 0); | ||
157 | if(strcmp(instr, test->instr) != 0) | ||
158 | { | ||
159 | printf("Test Failed \n" | ||
160 | "Code : 0x%0x\n" | ||
161 | "Expected : %s\n" | ||
162 | "Actual : %s\n", test->code, test->instr, instr); | ||
163 | failed++; | ||
164 | } | ||
165 | } | ||
166 | for(uint32_t i = 0; i < sizeof(test_branches_table)/sizeof(test_branches_table_entry_t); ++i) | ||
167 | { | ||
168 | test_branches_table_entry_t *test; | ||
169 | test = &test_branches_table[i]; | ||
170 | mips_disassem(&test->code, instr, 0); | ||
171 | //printf("DBG code address: %lx\n", (uint64_t)(&test->code)); | ||
172 | uint64_t loc = (uint64_t)test + 4 + (test->offset << 2); | ||
173 | //printf("DBG loc: %lx\n", loc); | ||
174 | char temp[256], address[16]; | ||
175 | strcpy(temp, test->instr); | ||
176 | sprintf(address, "0x%lx", loc); | ||
177 | strcat(temp, address); | ||
178 | if(strcmp(instr, temp) != 0) | ||
179 | { | ||
180 | printf("Test Failed \n" | ||
181 | "Code : 0x%0x\n" | ||
182 | "Expected : %s\n" | ||
183 | "Actual : %s\n", test->code, temp, instr); | ||
184 | failed++; | ||
185 | } | ||
186 | } | ||
187 | for(uint32_t i = 0; i < sizeof(test_jump_table)/sizeof(test_jump_table_entry_t); ++i) | ||
188 | { | ||
189 | test_jump_table_entry_t *test; | ||
190 | test = &test_jump_table[i]; | ||
191 | mips_disassem(&test->code, instr, 0); | ||
192 | //printf("DBG code address: %lx\n", (uint64_t)(&test->code)); | ||
193 | uint64_t loc = ((uint64_t)test & 0xfffffffff0000000) | (test->offset << 2); | ||
194 | //printf("DBG loc: %lx\n", loc); | ||
195 | char temp[256], address[16]; | ||
196 | strcpy(temp, test->instr); | ||
197 | sprintf(address, "0x%08lx", loc); | ||
198 | strcat(temp, address); | ||
199 | if(strcmp(instr, temp) != 0) | ||
200 | { | ||
201 | printf("Test Failed \n" | ||
202 | "Code : 0x%0x\n" | ||
203 | "Expected : '%s'\n" | ||
204 | "Actual : '%s'\n", test->code, temp, instr); | ||
205 | failed++; | ||
206 | } | ||
207 | } | ||
208 | if(failed == 0) | ||
209 | { | ||
210 | printf("All tests PASSED\n"); | ||
211 | return 0; | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | printf("%d tests FAILED\n", failed); | ||
216 | return -1; | ||
217 | } | ||
218 | } | ||
diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp index 148b6f44d..efa6d87bf 100644 --- a/libpixelflinger/tests/codegen/codegen.cpp +++ b/libpixelflinger/tests/codegen/codegen.cpp | |||
@@ -11,16 +11,18 @@ | |||
11 | #include "codeflinger/ARMAssembler.h" | 11 | #include "codeflinger/ARMAssembler.h" |
12 | #if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 12 | #if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 |
13 | #include "codeflinger/MIPSAssembler.h" | 13 | #include "codeflinger/MIPSAssembler.h" |
14 | #elif defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6 | ||
15 | #include "codeflinger/MIPS64Assembler.h" | ||
14 | #endif | 16 | #endif |
15 | #include "codeflinger/Arm64Assembler.h" | 17 | #include "codeflinger/Arm64Assembler.h" |
16 | 18 | ||
17 | #if defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6) || defined(__aarch64__) | 19 | #if defined(__arm__) || (defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6))) || defined(__aarch64__) |
18 | # define ANDROID_ARM_CODEGEN 1 | 20 | # define ANDROID_ARM_CODEGEN 1 |
19 | #else | 21 | #else |
20 | # define ANDROID_ARM_CODEGEN 0 | 22 | # define ANDROID_ARM_CODEGEN 0 |
21 | #endif | 23 | #endif |
22 | 24 | ||
23 | #if defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6 | 25 | #if defined(__mips__) && ((!defined(__LP64__) && __mips_isa_rev < 6) || (defined(__LP64__) && __mips_isa_rev == 6)) |
24 | #define ASSEMBLY_SCRATCH_SIZE 4096 | 26 | #define ASSEMBLY_SCRATCH_SIZE 4096 |
25 | #elif defined(__aarch64__) | 27 | #elif defined(__aarch64__) |
26 | #define ASSEMBLY_SCRATCH_SIZE 8192 | 28 | #define ASSEMBLY_SCRATCH_SIZE 8192 |
@@ -58,6 +60,10 @@ static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1) | |||
58 | GGLAssembler assembler( new ArmToMipsAssembler(a) ); | 60 | GGLAssembler assembler( new ArmToMipsAssembler(a) ); |
59 | #endif | 61 | #endif |
60 | 62 | ||
63 | #if defined(__mips__) && defined(__LP64__) && __mips_isa_rev == 6 | ||
64 | GGLAssembler assembler( new ArmToMips64Assembler(a) ); | ||
65 | #endif | ||
66 | |||
61 | #if defined(__aarch64__) | 67 | #if defined(__aarch64__) |
62 | GGLAssembler assembler( new ArmToArm64Assembler(a) ); | 68 | GGLAssembler assembler( new ArmToArm64Assembler(a) ); |
63 | #endif | 69 | #endif |