This source file includes following definitions.
- defstruct
- new_list
- free_list
- new_node
- l_search
- l_insert
- l_remove
- set_patch_old_values
- append
- print_ascii_str
- xhex8
- ahex8
- yhex8
- sub_hex8
- sub_ahex8
- reg
- num
- instr_disassemble
- disassemble1
- disassemble
- find_end
- swiname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stdint.h>
46 #include <string.h>
47 #include <ctype.h>
48 #include <sys/stat.h>
49
50 #include "stubs_load.h"
51 #include "firmware_load.h"
52 #include "chdk_dasm.h"
53
54
55
56 declstruct(Instruction);
57
58 typedef enum {
59 target_None,
60 target_Data,
61 target_FloatS,
62 target_FloatD,
63 target_FloatE,
64 target_FloatP,
65 target_Code,
66 target_Unknown
67 } eTargetType;
68
69 defstruct(Instruction) {
70 char text[128];
71 int undefined;
72 int badbits;
73 int oddbits;
74 int is_SWI;
75 t_value swinum;
76 t_address target;
77 eTargetType target_type;
78 int offset;
79 char * addrstart;
80 t_value instr ;
81 };
82
83 char *patch_func_name;
84 t_address patch_new_val;
85 t_address patch_old_val;
86 char *patch_old_func_name;
87 int patch_ref_address[20];
88 char patch_ref_name[20][256];
89 int save_patch_ref;
90 char *patch_comment;
91
92 static char * reg_names[16] = {
93 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "SP", "LR", "PC"
94 };
95
96 sDisOptions options = {
97 disopt_CommaSpace|disopt_exclude_dcd,
98 reg_names
99 };
100
101
102
103 #define Sbit (1<<20)
104 #define Lbit (1<<20)
105 #define Wbit (1<<21)
106 #define Bbit (1<<22)
107 #define Ubit (1<<23)
108 #define Pbit (1<<24)
109 #define Ibit (1<<25)
110
111 #define SPSRbit (1<<22)
112
113
114
115 #define RD(x) ((x)<<12)
116 #define RN(x) ((x)<<16)
117 #define CP(x) ((x)<<8)
118 #define RDbits RD(15)
119 #define RNbits RN(15)
120 #define CPbits CP(15)
121 #define RD_is(x) ((instr&RDbits)==RD(x))
122 #define RN_is(x) ((instr&RNbits)==RN(x))
123 #define CP_is(x) ((instr&CPbits)==CP(x))
124
125
126
127
128 #define BitsDiffer(a,b) ((instr^(instr>>(b-a)))&(1<<a))
129
130
131
132
133
134
135
136 struct lnode {
137 struct lnode *next;
138 t_address address;
139 t_value data ;
140 };
141
142 struct llist {
143 struct lnode *head;
144 int size;
145 };
146
147
148
149
150 struct llist * new_list()
151 {
152 struct llist *lst;
153
154 lst = (struct llist *) malloc(sizeof(struct llist));
155 if (lst == NULL) {
156 printf("\n **new_list() : malloc error");
157 return NULL;
158 }
159 lst->head = 0;
160 lst->size = 0;
161
162 return lst;
163 }
164
165 void free_list(struct llist *lst)
166 {
167 if (lst)
168 {
169 struct lnode *p, *n;
170 p = lst->head;
171 while (p)
172 {
173 n = p->next;
174 free(p);
175 p = n;
176 }
177 free(lst);
178 }
179 }
180
181
182
183
184 struct lnode * new_node(t_address address, t_value data) {
185 struct lnode *node;
186
187 node = (struct lnode *) malloc (sizeof (struct lnode));
188 if (node == NULL) {
189 printf("\n **new_node() : malloc error");
190 return NULL;
191 }
192 node->address = address;
193 node->data = data;
194 node->next = 0;
195
196 return node;
197 }
198
199
200
201
202 struct lnode * l_search(struct llist *ls, t_address address) {
203 struct lnode *node;
204
205 node = ls->head;
206 while ( node != NULL && node->address != address ) {
207 node = node->next ;
208 }
209 if (node == NULL) {
210 return 0;
211 }
212
213 return node;
214 }
215
216
217
218
219 int l_insert(struct llist *ls, t_address address, t_value data)
220 {
221 struct lnode *node;
222
223 if( l_search(ls, address)) return -1 ;
224 node = new_node(address, data);
225 if (node == NULL) return 0;
226 node->next = ls->head;
227 ls->head = node;
228 (ls->size)++;
229
230 return 1;
231 }
232
233 void l_remove(struct llist *ls, t_address addr)
234 {
235 if (ls)
236 {
237 struct lnode *p, *l;
238 l = 0;
239 p = ls->head;
240 while (p)
241 {
242 if (p->address == addr)
243 {
244 if (l)
245 l->next = p->next;
246 else
247 ls->head = p->next;
248 (ls->size)--;
249 return;
250 }
251 l = p;
252 p = p->next;
253 }
254 }
255 }
256
257
258
259
260
261 struct llist *dcd_list;
262 struct llist *branch_list;
263
264
265
266
267
268 static void set_patch_old_values(t_address w, char *nm)
269 {
270 patch_old_val = w;
271 patch_old_func_name = nm;
272 }
273
274 extern void swiname(t_value, char *, size_t);
275
276
277
278
279 static char * append(char * op, const char *ip) {
280 char c;
281 while ((c=*ip++)!=0) *op++=c;
282 return op;
283 }
284
285 static char * print_ascii_str(firmware *fw, char *op, t_value w)
286 {
287 if (isASCIIstring(fw, w))
288 {
289 char s[500];
290 char *p = adr2ptr(fw, w);
291 int i = 0;
292 while (*p)
293 {
294 switch (*p)
295 {
296 case '\r':
297 s[i++] = '\\';
298 s[i++] = 'r';
299 break;
300 case '\n':
301 s[i++] = '\\';
302 s[i++] = 'n';
303 break;
304 case '\t':
305 s[i++] = '\\';
306 s[i++] = 't';
307 break;
308 default:
309 s[i++] = *p;
310 break;
311 }
312 p++;
313 }
314 s[i] = 0;
315 op += sprintf(op," /*'%s'*/",s);
316 }
317 return op;
318 }
319
320
321
322 static char * xhex8(firmware *fw, char * op, t_value w)
323 {
324 char *s = op;
325
326 if (options.flags & disopt_patch_value)
327 {
328 set_patch_old_values(w, 0);
329 w = patch_new_val;
330 }
331
332 if (options.flags & disopt_patch_branch)
333 {
334 set_patch_old_values(w, 0);
335 if (patch_func_name)
336 op += sprintf(op,"=%s",patch_func_name) ;
337 else
338 {
339 if (options.flags & disopt_comment_lines)
340 op += sprintf(op,"=_sub_%08X_my",w);
341 else
342 op += sprintf(op,"=sub_%08X_my",w);
343 }
344 if (save_patch_ref >= 0)
345 {
346 *op = 0;
347 patch_ref_address[save_patch_ref] = w;
348 strcpy(patch_ref_name[save_patch_ref],s+1);
349 }
350 }
351 else
352 {
353 op += sprintf(op,"=0x%X",w);
354 op = print_ascii_str(fw, op, w);
355 }
356
357 return op;
358 }
359
360
361
362
363 static char * ahex8(firmware *fw, char * op, t_value w)
364 {
365 struct lnode * lptr ;
366 lptr = l_search( dcd_list, w) ;
367
368 if ( lptr ) w = lptr->data ;
369 else l_insert(dcd_list, w, 0) ;
370
371 return xhex8(fw, op, w);
372 }
373
374
375
376 static char * yhex8(firmware *fw, char * op, t_value w)
377 {
378 if (options.flags & disopt_patch_value)
379 {
380 set_patch_old_values(w, 0);
381 w = patch_new_val;
382 }
383 op += sprintf(op,"0x%X",w) ;
384 op = print_ascii_str(fw, op, w);
385 return op;
386 }
387
388
389
390 static char * sub_hex8(firmware *fw, char * op, t_value w)
391 {
392 if (options.flags & disopt_remember_branches)
393 l_insert(branch_list, w, 0) ;
394
395 char *s = op;
396
397
398 if (w >= fw->base)
399 w = followBranch(fw,w,1);
400 osig *o = find_sig_val_by_type(fw->sv->stubs, w, TYPE_NHSTUB);
401
402 if ((options.flags & disopt_patch_branch) && patch_func_name)
403 {
404 set_patch_old_values(w, (o) ? o->nm : 0);
405 op += sprintf(op,"%s",patch_func_name);
406 }
407 else
408 {
409 if (o && !o->is_comment)
410 {
411 op += sprintf(op,"_%s",o->nm);
412 }
413 else
414 {
415 if (( w >= options.start_address )&&( w <= options.end_address ))
416 {
417 op += sprintf(op,"loc_%08X",w);
418 }
419 else
420 {
421 if (options.flags & disopt_comment_lines)
422 op += sprintf(op,"_sub_%08X",w);
423 else
424 {
425
426 t_value v = fwval(fw,adr2idx(fw,w));
427 if (v == 0xE12FFF1E)
428 {
429
430 op += sprintf(op,"_sub_%08X",w);
431 options.flags |= disopt_nullsub_call;
432 }
433 else
434 {
435 op += sprintf(op,"sub_%08X",w);
436 if (o && o->is_comment)
437 op += sprintf(op," /*_%s*/",o->nm);
438 }
439 }
440 }
441 if (options.flags & disopt_patch_branch)
442 {
443 set_patch_old_values(w, 0);
444 op += sprintf(op,"_my");
445 }
446 }
447 }
448
449 if ((save_patch_ref >= 0) && (options.flags & disopt_patch_branch))
450 {
451 *op = 0;
452 patch_ref_address[save_patch_ref] = w;
453 strcpy(patch_ref_name[save_patch_ref],s);
454 }
455
456 return op;
457 }
458
459 static char * sub_ahex8(firmware *fw, char * op, t_value w)
460 {
461 struct lnode * lptr ;
462 lptr = l_search( dcd_list, w) ;
463
464 if ( !lptr )
465 l_insert(dcd_list, w, 0) ;
466
467 w = fwval(fw,adr2idx(fw,w));
468 return sub_hex8(fw, op, w);
469 }
470
471
472
473 static char * reg(char * op, char c, t_value n) {
474 *op++=c;
475 n&=15;
476 if (n>=10) { *op++='1'; n+='0'-10; } else n+='0';
477 *op++=(char)n;
478
479 return op;
480 }
481
482
483
484
485 static char * num(char * op, t_value w, t_value decmax)
486 {
487 char tmpbuf[16] ;
488 char * tptr ;
489 tptr = tmpbuf ;
490
491 if (options.flags & disopt_patch_value)
492 {
493 set_patch_old_values(w, 0);
494 w = patch_new_val;
495 }
496
497 if ( w<decmax ) sprintf( tptr, "%d", w) ;
498 else
499 {
500 if (w < 16)
501 sprintf( tptr, "0x%X", w);
502 else
503 sprintf( tptr, "0x%X", w);
504 }
505 tptr = tmpbuf ;
506 while(*tptr) *op++ = *tptr++ ;
507 return op;
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567 extern pInstruction instr_disassemble(firmware *fw, t_value instr, t_address addr, pDisOptions opts) {
568 static char flagchars[4];
569 static sInstruction result;
570 const char * mnemonic = 0;
571 char * flagp = flagchars;
572 const char * format = 0;
573 t_value fpn;
574 eTargetType poss_tt = target_None;
575 int is_v4 = 0;
576
577 options.flags &= ~disopt_nullsub_call;
578
579
580
581 fpn = ((instr>>15)&1) + ((instr>>21)&2);
582
583 result.undefined =
584 result.badbits =
585 result.oddbits =
586 result.instr =
587 result.is_SWI = 0;
588 result.target_type = target_None;
589 result.offset = 0x80000000;
590 result.addrstart = 0;
591
592
593 static char _i_mul[4][6] = { "UMULL", "UMLAL", "SMULL", "SMLAL" };
594 static char _i_ldr_str[2][4] = { "LDR", "STR" };
595 static char _i_str_ldr[2][4] = { "STR", "LDR" };
596 static char _i_stm_ldm[2][4] = { "STM", "LDM" };
597 static char _i_stf_ldf[2][4] = { "STF", "LDF" };
598 static char _i_stc_ldc[2][4] = { "STC", "LDC" };
599 static char _i_sfm_lfm[2][4] = { "SFM", "LFM" };
600 static char _i_b_bl[2][3] = { "B", "BL" };
601 static char _i_alu[16][4] = {
602 "AND","EOR","SUB","RSB","ADD","ADC","SBC","RSC",
603 "TST","TEQ","CMP","CMN","ORR","MOV","BIC","MVN"
604 };
605 static char _i_cmf[4][5] = { "CMF","CNF","CMFE","CNFE" };
606 static char _i_flt[6][4] = { "FLT","FIX","WFS","RFS","WFC","RFC" };
607 static char _i_mcr_mrc[2][4] = { "MCR","MRC" };
608 static char _i_copro[32][4] = {
609
610 "ADF","MUF","SUF","RSF",
611 "DVF","RDF","POW","RPW",
612 "RMF","FML","FDV","FRD",
613 "POL","***","***","***",
614
615 "MVF","MNF","ABS","RND",
616 "SQT","LOG","LGN","EXP",
617 "SIN","COS","TAN","ASN",
618 "ACS","ATN","URD","NRM"
619 };
620 static char _i_lsl_lsr[4][4] = { "LSL","LSR","ASR","ROR" };
621 static char _i_stk[4][2] = { "ED","EA","FD","FA" };
622 static char _i_cond[16][2] = { "EQ","NE","CS","CC","MI","PL","VS","VC","HI","LS","GE","LT","GT","LE","AL","NV" };
623
624 switch ((instr>>24)&15) {
625
626 case 0:
627 if ((instr&(15<<4))!=(9<<4)) goto lMaybeLDRHetc;
628
629 if (instr&(1<<23)) {
630 mnemonic = _i_mul[(instr>>21)&3];
631 format = "3,4,0,2";
632 }
633 else {
634 if (instr&(1<<22)) goto laUndefined;
635
636 if (instr&(1<<21)) {
637 mnemonic = "MLA";
638 format = "4,0,2,3";
639 }
640 else {
641 mnemonic = "MUL";
642 format = "4,0,2";
643 }
644 }
645 if (instr&Sbit) *flagp++='S';
646 break;
647
648 case 1:
649 case 3:
650
651 if ((instr&0x0FF000F0)==0x01200010) {
652 mnemonic = "BX";
653 format = "0";
654 break;
655 }
656 if ((instr&0x0FF000F0)==0x01200030) {
657 mnemonic = "BLX";
658 format = "0";
659 break;
660 }
661 if ((instr&0x02B00FF0)==0x00000090) {
662 mnemonic = "SWP";
663 format = "3,0,[4]";
664 if (instr&Bbit) *flagp++='B';
665 break;
666 }
667 if ((instr&0x02BF0FFF)==0x000F0000) {
668 mnemonic = "MRS";
669 format = (instr&SPSRbit) ? "3,SPSR" : "3,CPSR";
670 break;
671 }
672
673 if ((instr&0x0FB00010)==0x03200000) {
674 mnemonic = "MSR";
675 format = (instr&SPSRbit) ? "SPSR,0" : "CPSR,0";
676 break;
677 }
678
679 if ((instr&0x0FB00010)==0x01200000) {
680 mnemonic = "MSR";
681 format = (instr&SPSRbit) ? "SPSR_cxsf,*" : "CPSR_cxsf,*";
682 if (!(instr&Ibit) && (instr&(15<<4)))
683 goto lMaybeLDRHetc;
684 break;
685 }
686
687
688 lMaybeLDRHetc:
689 if ( (instr&(14<<24))==0 && ((instr&(9<<4))==(9<<4)) )
690 {
691 if ((instr&(Wbit+Pbit))==Wbit) goto lbUndefined;
692 if ((instr&(Lbit+(1<<6)))==(1<<6))
693 {
694 if ((instr&(1<<6))!=(1<<6)) goto lcUndefined ;
695 mnemonic = _i_ldr_str[(instr & 0x0000020) >> 5];
696 if (instr&(1<<6)) *flagp++='D';
697 format = "3,/";
698 if (!(instr&(1<<22))) instr |= Ibit;
699 is_v4=1;
700 }
701 else
702 {
703 mnemonic = _i_str_ldr[(instr&Lbit) >> 20];
704 if (instr&(1<<6)) *flagp++='S';
705 *flagp++ = (instr&(1<<5)) ? 'H' : 'B';
706 format = "3,/";
707 if (!(instr&(1<<22))) instr |= Ibit;
708 is_v4=1;
709 }
710 break;
711 }
712
713 case 2:
714 { t_value op21 = instr&(15<<21);
715 if ((op21==(2<<21) || (op21==(4<<21)))
716 && ((instr&(RNbits+Ibit+Sbit))==RN(15)+Ibit)
717 ) {
718
719 mnemonic = "LDR";
720 format = "3,.";
721 if ((instr&(30<<7))!=0 && !(instr&3)) result.oddbits=1;
722 break;
723 }
724 if ((op21==(4<<21))
725 && ((instr&(Ibit))==Ibit)
726 && ((instr&0xFFF)==0)
727 ) {
728
729 mnemonic = "MOV";
730 format = "3,4";
731 if (instr&Sbit && (op21<(8<<21) || op21>=(12<<21))) *flagp++='S';
732 break;
733 }
734 mnemonic = _i_alu[op21 >> 21];
735
736
737 if (op21 < ( 8<<21)) format = "3,4,*";
738 else if (op21 < (12<<21)) {
739 format = "4,*";
740 if (instr&RDbits) {
741 if ((instr&Sbit) && RD_is(15))
742 *flagp++='P';
743 else result.oddbits=1;
744 }
745 if (!(instr&Sbit)) goto ldUndefined;
746 }
747 else if (op21 & (1<<21)) {
748 format = "3,*";
749 if (instr&RNbits) result.oddbits=1;
750 }
751 else format = "3,4,*";
752 if (instr&Sbit && (op21<(8<<21) || op21>=(12<<21))) *flagp++='S';
753 }
754 break;
755
756 case 4:
757 case 5:
758 case 6:
759 case 7:
760 if ((instr&Ibit) && (instr&(1<<4))) goto leUndefined;
761 mnemonic = _i_str_ldr[(instr&Lbit) >> 20];
762 format = "3,/";
763 if (instr&Bbit) *flagp++='B';
764 if ((instr&(Wbit+Pbit))==Wbit) *flagp++='T';
765 poss_tt = target_Data;
766 break;
767
768 case 8:
769 case 9:
770 mnemonic = _i_stm_ldm[(instr&Lbit) >> 20];
771 if (RN_is(13)) {
772 t_value x = (instr&(3<<23)) >> 23;
773 if (instr&Lbit) x^=3;
774 {
775 const char * foo = _i_stk[x];
776 *flagp++ = *foo++;
777 *flagp++ = *foo;
778 }
779 }
780 else {
781 *flagp++ = (instr&Ubit) ? 'I' : 'D';
782 *flagp++ = (instr&Pbit) ? 'B' : 'A';
783 }
784 format = "4',%";
785 break;
786
787 case 10:
788 case 11:
789 mnemonic = _i_b_bl[(instr&(1<<24))>>24];
790 format = "&";
791 break;
792
793 case 12:
794 case 13:
795 if (CP_is(1)) {
796 mnemonic = _i_stf_ldf[(instr&Lbit) >> 20];
797 format = "8,/";
798 *flagp++ = "SDEP"[fpn];
799 poss_tt = (eTargetType)(target_FloatS+fpn);
800 }
801 else if (CP_is(2)) {
802 mnemonic = _i_sfm_lfm[(instr&Lbit) >> 20];
803 if (!fpn) fpn=4;
804 if (RN_is(13) && BitsDiffer(23,24)) {
805 if ((instr&255)!=fpn) goto lNonStackLFM;
806 if (BitsDiffer(20,24)) {
807 *flagp++ = 'F'; *flagp++ = 'D';
808 }
809 else {
810 *flagp++ = 'E'; *flagp++ = 'A';
811 }
812 format = "8,(,[4]'";
813 }
814 else {
815 lNonStackLFM:
816 format = "8,(,/";
817 poss_tt = target_FloatE;
818 }
819 }
820 else {
821 mnemonic = _i_stc_ldc[(instr&Lbit) >> 20];
822 format = ";,\004,/";
823 if (instr&(1<<22)) *flagp++ = 'L';
824 poss_tt = target_Unknown;
825 }
826 break;
827
828 case 14:
829 if (instr&(1<<4)) {
830 if (CP_is(1)) {
831 if ((instr&Lbit) && RD_is(15)) {
832 if (!(instr&(1<<23))) goto lfUndefined;
833 mnemonic = _i_cmf[(instr&(3<<21)) >> 21];
834 format = "9,+";
835 if (instr&((1<<19)+(7<<5)))
836 result.badbits=1;
837 }
838 else {
839 t_value op20 = instr&(15<<20);
840 if (op20>=6<<20) goto lgUndefined;
841 mnemonic = _i_flt[op20>>20];
842 if (op20==0) {
843 format = "9,3";
844 { char c = "SDE*"[((instr>>7)&1) + ((instr>>18)&2)];
845 if (c=='*') goto lhUndefined; else *flagp++=c;
846 }
847 if (instr&15) result.oddbits=1;
848 }
849 else {
850 if (instr&((1<<7)+(1<<19)))
851 result.badbits=1;
852 if (op20==1<<20) {
853 format = "3,+";
854 if (opts->flags&disopt_FIXS)
855 *flagp++ = "SDEP"[((instr>>7)&1) + ((instr>>18)&2)];
856 *flagp++ = "\0PMZ"[(instr&(3<<5))>>5];
857 if (instr&(7<<15)) result.oddbits=1;
858 if (instr&(1<<3)) result.badbits=1;
859 }
860 else {
861 format = "3";
862 if (instr&(3<<5)) result.badbits=1;
863 if (instr&(15+(7<<15))) result.oddbits=1;
864 }
865 }
866 }
867 }
868 else {
869 mnemonic = _i_mcr_mrc[(instr&Lbit)>>20];
870 format = ";,:,3,\005,\001-";
871 }
872 }
873 else {
874 if (CP_is(1)) {
875 mnemonic = _i_copro[
876 ((instr&(15<<20)) >> 20)
877 + ((instr&(1<<15)) >> 11)];
878 format = (instr&(1<<15)) ? "8,+" : "8,9,+";
879 *flagp++ = "SDE*"[((instr>>7)&1) + ((instr>>18)&2)];
880 *flagp++ = "\0PMZ"[(instr&(3<<5))>>5];
881 if (*mnemonic=='*' || *flagchars=='*') goto liUndefined;
882 }
883 else {
884 mnemonic = "CDP";
885 format = ";,),\004,\005,\001-";
886 }
887 }
888 break;
889 case 15:
890
891
892
893
894
895
896 goto lUndefined;
897
898
899
900
901
902
903 laUndefined:
904 strcpy(result.text, "Undefined instruction a"); goto lUndefined ;
905 lbUndefined:
906 strcpy(result.text, "Undefined instruction b"); goto lUndefined ;
907 lcUndefined:
908 strcpy(result.text, "Undefined instruction c"); goto lUndefined ;
909 ldUndefined:
910 strcpy(result.text, "Undefined instruction d"); goto lUndefined ;
911 leUndefined:
912 strcpy(result.text, "Undefined instruction e"); goto lUndefined ;
913 lfUndefined:
914 strcpy(result.text, "Undefined instruction f"); goto lUndefined ;
915 lgUndefined:
916 strcpy(result.text, "Undefined instruction g"); goto lUndefined ;
917 lhUndefined:
918 strcpy(result.text, "Undefined instruction h"); goto lUndefined ;
919 liUndefined:
920 strcpy(result.text, "Undefined instruction i"); goto lUndefined ;
921 ljUndefined:
922 strcpy(result.text, "Undefined instruction j"); goto lUndefined ;
923 lkUndefined:
924 strcpy(result.text, "Undefined instruction k"); goto lUndefined ;
925 llUndefined:
926 strcpy(result.text, "Undefined instruction l"); goto lUndefined ;
927 lUndefined:
928
929
930
931
932
933
934 result.badbits = 1;
935 break;
936 }
937
938 if (result.oddbits || result.badbits) {
939 result.instr = instr ;
940 mnemonic = ".long";
941 format = "=";
942 instr = 14 << 28;
943 result.oddbits = result.badbits = 0;
944 result.text[0] = flagchars[0] = 0;
945 }
946
947 *flagp=0;
948
949
950
951 { char * op = result.text;
952
953
954
955 op = append(op,mnemonic);
956
957
958
959 {
960 t_value cond = instr>>28;
961 if (cond!=14) {
962 const char * ip = _i_cond[cond];
963 *op++ = *ip++;
964 *op++ = *ip;
965 }
966 }
967
968
969
970 { const char * ip = flagchars;
971 while (*ip) *op++ = *ip++;
972 }
973
974
975
976 do {
977 *op++ = ' ';
978 *op = 0 ;
979 } while ( strlen( result.text ) < 8 ) ;
980
981
982
983 { const char * ip = format;
984 char c;
985
986 char * * regnames = opts->regnames;
987 t_value oflags = opts->flags;
988
989 while ((c=*ip++) != 0) {
990 switch(c) {
991 case '=':
992 if (((unsigned long)result.instr > (unsigned long)addr) && ((unsigned long)result.instr < (unsigned long)addr+0x1000)) {
993 result.addrstart = op;
994 op = sub_hex8(fw, op, result.instr);
995 }
996 else {
997 op = yhex8(fw, op, result.instr);
998 }
999 break;
1000 case '$':
1001 result.is_SWI = 1;
1002 result.swinum = instr&0x00FFFFFF;
1003 result.addrstart = op;
1004 if (oflags&disopt_SWInames) {
1005 swiname(result.swinum, op, 128-(op-result.text));
1006 op += strlen(op);
1007 }
1008 else
1009 op += sprintf(op, "&%X", result.swinum);
1010 break;
1011 case '%':
1012 *op++='{';
1013 { t_value w = instr&0xFFFF;
1014 int i=0;
1015 while (w) {
1016 int j;
1017 while (!(w&(1ul<<i))) ++i;
1018 for (j=i+1; w&(1ul<<j); ++j) ;
1019 --j;
1020
1021 op = append(op, regnames[i]);
1022 if (j-i) {
1023 *op++ = (j-i>1) ? '-' : ',';
1024 op = append(op, regnames[j]);
1025 }
1026 i=j; w=(w>>(j+1))<<(j+1);
1027 if (w) *op++=',';
1028 }
1029 }
1030 *op++='}';
1031 if (instr&(1<<22)) *op++='^';
1032 break;
1033 case '&':
1034
1035 { t_address target = ((t_address) addr ) + 8 + ((t_address) ((((int)instr)<<8) >>6 )) ;
1036 result.addrstart = op;
1037 op = sub_hex8(fw, op, target);
1038 result.target_type = target_Code;
1039 result.target = target;
1040 }
1041 break;
1042 case '\'':
1043 lPling:
1044 if (instr&Wbit) *op++='!';
1045 break;
1046 case '(':
1047 *op++ = (char)('0'+fpn);
1048 break;
1049 case ')':
1050 { t_value w = (instr>>20)&15;
1051 if (w>=10) { *op++='1'; *op++=(char)('0'-10+w); }
1052 else *op++=(char)(w+'0');
1053 }
1054 break;
1055
1056 case '*':
1057 case '.':
1058 if (instr&Ibit) {
1059
1060 t_value imm8 = (instr&255);
1061 t_value rot = (instr>>7)&30;
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 imm8 = (imm8>>rot) | (imm8<<(32-rot));
1074 if (c=='*') {
1075 *op++='#';
1076 if (imm8>256 && ((imm8&(imm8-1))==0)) {
1077
1078
1079
1080
1081 { int n=0;
1082 while (!(imm8&15)) { n+=4; imm8=imm8>>4; }
1083
1084 n += (0x30002010 >> 4*(imm8-1))&15;
1085 n= 1<<n ;
1086 op = yhex8(fw, op, n);
1087 }
1088
1089 }
1090 else {
1091 if (((int)imm8)<0 && ((int)imm8)>-100) {
1092 *op++='-'; imm8=-imm8;
1093 }
1094 op = num(op, imm8, 10);
1095 }
1096 }
1097 else {
1098 t_address a = addr+8;
1099 if (instr&(1<<22)) a-=imm8; else a+=imm8;
1100 result.addrstart=op;
1101 op = xhex8(fw, op, a);
1102 result.target=a; result.target_type=target_Unknown;
1103 }
1104
1105 }
1106 else {
1107
1108 const char * rot = _i_lsl_lsr[(instr&(3<<5)) >> 5];
1109 op = append(op, regnames[instr&15]);
1110 if (instr&(1<<4)) {
1111
1112 if (instr&(1<<7)) goto ljUndefined;
1113 *op++=','; if (oflags&disopt_CommaSpace) *op++=' ';
1114 op = append(op,rot); *op++=' ';
1115 op = append(op,regnames[(instr&(15<<8))>>8]);
1116 }
1117 else {
1118
1119 t_value n = instr&(31<<7);
1120 if (!n) {
1121 if (!(instr&(3<<5))) break;
1122 else if ((instr&(3<<5))==(3<<5)) {
1123 op = append(op, ",RRX");
1124 break;
1125 }
1126 else n=32<<7;
1127 }
1128 *op++ = ','; if (oflags&disopt_CommaSpace) *op++=' ';
1129 op = num(append(append(op,rot),"#"),n>>7,32);
1130 }
1131 }
1132 break;
1133 case '+':
1134 if (instr&(1<<3)) {
1135 t_value w = instr&7;
1136 *op++='#';
1137 if (w<6) *op++=(char)('0'+w);
1138 else op = append(op, w==6 ? "0.5" : "10");
1139 }
1140 else {
1141 *op++='f';
1142 *op++=(char)('0'+(instr&7));
1143 }
1144 break;
1145 case ',':
1146 *op++=',';
1147 if (oflags&disopt_CommaSpace) *op++=' ';
1148 break;
1149 case '-':
1150 { t_value w = instr&(7<<5);
1151 if (w) {
1152 *op++=',';
1153 if (oflags&disopt_CommaSpace) *op++=' ';
1154 *op++ = (char)('0'+(w>>5));
1155 }
1156 }
1157 break;
1158 case '/':
1159 result.addrstart = op;
1160 *op++='[';
1161
1162 op = append(op, regnames[(instr&RNbits)>>16]);
1163
1164 if (!(instr&Pbit)) *op++=']';
1165
1166 *op++=',';
1167
1168 if (oflags&disopt_CommaSpace) *op++=' ';
1169
1170
1171 if (instr&Ibit) {
1172
1173 if (!(instr&Ubit)) *op++='-';
1174
1175
1176
1177
1178 instr ^= Ibit;
1179 if (instr&(1<<4)) {
1180
1181 if (is_v4 && !(instr&(15<<8))) {
1182 ip = (instr&Pbit) ? "0]" : "0";
1183 break;
1184 }
1185 }
1186
1187
1188
1189
1190 if (instr&Pbit) ip="*]'";
1191 else if (instr&(1<<27)) {
1192 if (CP_is(1) || CP_is(2)) {
1193 if (!(instr&Wbit)) goto lkUndefined;
1194 ip="*";
1195 }
1196 else ip="*'";
1197 }
1198 else ip="*";
1199 }
1200 else {
1201
1202 t_value offset;
1203 if (instr&(1<<27)) {
1204 offset = (instr&255)<<2;
1205 }
1206
1207 else if (is_v4) offset = (instr&15) + ((instr&(15<<8))>>4);
1208 else {
1209 offset = instr&0xFFF;
1210 }
1211
1212 if ( offset == 0 ){
1213 if (oflags&disopt_CommaSpace) op-- ;
1214 op-- ; *op++=']'; goto lPling; }
1215
1216 *op++='#';
1217 if (!(instr&Ubit))
1218 {
1219 if (offset) *op++='-';
1220 else result.oddbits=1;
1221 result.offset = -offset;
1222 }
1223 else result.offset = offset;
1224
1225 op = num(op, offset, 10);
1226 if (RN_is(15) && (instr&Pbit))
1227 {
1228
1229 result.target_type = poss_tt;
1230 result.target = (instr&Ubit) ? addr+8 + offset
1231 : addr+8 - offset;
1232 if (!(instr&Wbit))
1233 {
1234
1235 if (RD_is(15))
1236 op = sub_ahex8(fw, result.addrstart, result.target);
1237 else
1238 op = ahex8(fw, result.addrstart, result.target);
1239 break;
1240 }
1241 }
1242 if (instr&Pbit) { *op++=']'; goto lPling; }
1243 else if (instr&(1<<27)) {
1244 if (CP_is(1) || CP_is(2)) {
1245 if (!(instr&Wbit)) goto llUndefined;
1246 }
1247 else goto lPling;
1248 }
1249 }
1250 break;
1251
1252 case '0': case '1': case '2': case '3': case '4':
1253 op = append(op, regnames[(instr>>(4*(c-'0')))&15]);
1254 break;
1255 case '5': case '6': case '7': case '8': case '9':
1256 *op++='f';
1257 *op++=(char)('0' + ((instr>>(4*(c-'5')))&7));
1258 break;
1259 case ':':
1260 *op++ = (char)('0' + ((instr>>21)&7));
1261 break;
1262 case ';':
1263 op = reg(op, 'p', instr>>8);
1264 break;
1265 default:
1266 if (c<=5)
1267 op = reg(op, 'c', instr >> (4*(c-1)));
1268 else *op++ = c;
1269 }
1270 }
1271 *op=0;
1272 }
1273 }
1274
1275
1276
1277 return &result;
1278 }
1279
1280
1281 t_address addr, last_used_addr;
1282
1283 void disassemble1(firmware *fw, t_address start, t_value length)
1284 {
1285 t_value w;
1286
1287 free(dcd_list);
1288 dcd_list = new_list();
1289 free(branch_list);
1290 branch_list = new_list();
1291
1292
1293 int pass;
1294 for ( pass = 1 ; pass <=3 ; pass++ )
1295 {
1296 if ( pass == 2 )
1297 {
1298 struct lnode* lptr = dcd_list->head;
1299 while ( lptr != NULL )
1300 {
1301 addr = (t_address) lptr->address ;
1302 w = fwval(fw,adr2idx(fw,addr));
1303 lptr->data = w ;
1304 lptr = lptr->next ;
1305 }
1306 }
1307 else
1308 {
1309 addr = start ;
1310 t_value word_count = 0 ;
1311
1312 while (word_count < length )
1313 {
1314 w = fwval(fw,adr2idx(fw,addr));
1315 instr_disassemble(fw, w, addr, &options);
1316
1317 struct lnode* lptr = l_search(dcd_list,addr);
1318 if (!lptr)
1319 last_used_addr = addr;
1320
1321 word_count++ ;
1322 addr += 4;
1323 }
1324 }
1325 }
1326 }
1327
1328 void disassemble(firmware *fw, FILE *outfile, t_address start, t_value length)
1329 {
1330 t_value w;
1331
1332 int dcd_mode_on = 0;
1333
1334
1335 addr = start ;
1336 t_value word_count = 0 ;
1337
1338 while (word_count < length )
1339 {
1340 w = fwval(fw,adr2idx(fw,addr));
1341
1342 pInstruction instr = instr_disassemble(fw, w, addr, &options);
1343
1344 if (l_search(branch_list, addr))
1345 {
1346 fprintf(outfile,"\n\"loc_%08X:\\n\"\n", addr);
1347 dcd_mode_on = 0;
1348 }
1349 struct lnode* lptr = l_search(dcd_list,addr);
1350 if ( lptr || dcd_mode_on )
1351 {
1352 if ((options.flags & disopt_exclude_dcd) == 0)
1353 fprintf(outfile,"\"dword_%8.8X DCD 0x%X \\n\"\n", addr , w);
1354 dcd_mode_on = 1;
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369 }
1370 else
1371 {
1372 if (instr->undefined || instr->badbits || instr->oddbits) {
1373 fprintf(outfile,"Error: ");
1374 if (instr->undefined) fprintf(outfile,"[---undefined instr---] 0x%8.8X ", w);
1375 if (instr->badbits) fprintf(outfile, "[---illegal bits---] 0x%8.8X ", w);
1376 if (instr->oddbits) fprintf(outfile, "[---unexpected bits---] 0x%8.8X ", w);
1377 if ( !((instr->undefined) || (instr->badbits) || (instr->oddbits)) )
1378 fprintf(outfile, "[---unknown error---] 0x%8.8X ", w);
1379 if ( options.flags & disopt_print_address_mode)
1380 {
1381 fprintf(outfile,"// rom:%.8x 0x%8.8X \n", addr, w);
1382 }
1383 else fprintf(outfile,"\n");
1384 }
1385 else
1386 {
1387 strcat( instr->text, " \\n\"") ;
1388 if (options.flags & disopt_line_numbers) fprintf(outfile,"/*%3d*/",(addr - options.start_address) / 4 + 1);
1389 char *indent = "\" ";
1390 if (options.flags & (disopt_comment_lines|disopt_nullsub_call))
1391 indent = "//\" ";
1392 if (options.flags & disopt_indent_mneumonics_mode)
1393 fprintf(outfile," ");
1394 if (options.flags & disopt_print_address_mode)
1395 {
1396 fprintf(outfile,"%s%-40s // rom:%.8x 0x%8.8X", indent, instr->text, addr, w);
1397 }
1398 else fprintf(outfile,"%s%s", indent, instr->text);
1399
1400 if ((options.flags & disopt_patch_branch) || (options.flags & disopt_patch_value))
1401 {
1402 if (patch_old_func_name)
1403 fprintf(outfile," // --> Patched. Old value = _%s.", patch_old_func_name);
1404 else
1405 fprintf(outfile," // --> Patched. Old value = 0x%X.", patch_old_val);
1406 if ((options.flags & disopt_patch_comment) && patch_comment)
1407 {
1408 fprintf(outfile, " %s", patch_comment);
1409 patch_comment = 0;
1410 }
1411 }
1412 else if ((options.flags & disopt_patch_comment) && patch_comment)
1413 {
1414 fprintf(outfile, " // %s", patch_comment);
1415 patch_comment = 0;
1416 }
1417 else if (options.flags & disopt_nullsub_call)
1418 {
1419 fprintf(outfile," // --> Nullsub call removed.");
1420 }
1421 fprintf(outfile,"\n");
1422 }
1423 }
1424
1425 word_count++ ;
1426 addr += 4;
1427 }
1428 }
1429
1430 t_address find_end(firmware *fw, t_address start)
1431 {
1432 int i;
1433 start = adr2idx(fw,start);
1434 for (i=0; i<500; i++, start++)
1435 if ((fwval(fw,start+1) & 0xFFFF4000) == 0xE92D4000)
1436 {
1437 int j;
1438 for (j=0; j<50; j++, start--)
1439 {
1440 if ((fwval(fw,start) & 0xFF000000) == 0xEA000000)
1441 {
1442 return idx2adr(fw,start);
1443 }
1444 if ((fwval(fw,start) & 0xFFFF8000) == 0xE8BD8000)
1445 {
1446 return idx2adr(fw,start);
1447 }
1448 if ((fwval(fw,start) & 0xFFFFFFF0) == 0xE12FFF10)
1449 {
1450 return idx2adr(fw,start);
1451 }
1452 if ((fwval(fw,start) & 0xFFFFF000) == 0xE49DF000)
1453 {
1454 return idx2adr(fw,start);
1455 }
1456 }
1457 return 0;
1458 }
1459 return 0;
1460 }
1461
1462
1463
1464 void swiname(__attribute__ ((unused))t_value w, __attribute__ ((unused))char * s, __attribute__ ((unused))size_t sz) { return; }
1465
1466