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", static_cast<int16_t>(0xffff) },
127 { 0x13df0008, "beq\ts8,ra,", 0x8 },
128 { 0x042100ff, "bgez\tat,", 0xff },
129 { 0x1c40ff00, "bgtz\tv0,", static_cast<int16_t>(0xff00) },
130 { 0x18605555, "blez\tv1,", 0x5555 },
131 { 0x0480aaaa, "bltz\ta0,", static_cast<int16_t>(0xaaaa) },
132 { 0x14a68888, "bne\ta1,a2,", static_cast<int16_t>(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
main()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 }
219