1
2
3#include <common.h>
4
5#include <linux/ctype.h>
6#include <bedbug/bedbug.h>
7#include <bedbug/ppc.h>
8#include <bedbug/regs.h>
9#include <bedbug/tables.h>
10
11#define Elf32_Word unsigned long
12
13
14
15
16
17
18
19
20#ifdef USE_SOURCE_CODE
21extern int line_info_from_addr __P ((Elf32_Word, char *, char *, int *));
22extern struct symreflist *symByAddr;
23extern char *symbol_name_from_addr __P ((Elf32_Word, int, int *));
24#endif
25
26int print_operands __P ((struct ppc_ctx *));
27int get_operand_value __P ((struct opcode *, unsigned long,
28 enum OP_FIELD, unsigned long *));
29struct opcode *find_opcode __P ((unsigned long));
30struct opcode *find_opcode_by_name __P ((char *));
31char *spr_name __P ((int));
32int spr_value __P ((char *));
33char *tbr_name __P ((int));
34int tbr_value __P ((char *));
35int parse_operand __P ((unsigned long, struct opcode *,
36 struct operand *, char *, int *));
37int get_word __P ((char **, char *));
38long read_number __P ((char *));
39int downstring __P ((char *));
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,
80 int (*pfunc) (const char *), unsigned long flags)
81{
82 int i;
83 struct ppc_ctx ctx;
84
85#ifdef USE_SOURCE_CODE
86 int line_no = 0;
87 int last_line_no = 0;
88 char funcname[128] = { 0 };
89 char filename[256] = { 0 };
90 char last_funcname[128] = { 0 };
91 int symoffset;
92 char *symname;
93 char *cursym = (char *) 0;
94#endif
95
96
97 ctx.flags = flags;
98 ctx.virtual = virtual;
99
100
101
102 if (ctx.flags & F_RADOCTAL) {
103
104 strcpy (ctx.radix_fmt, "O%o");
105 } else if (ctx.flags & F_RADUDECIMAL) {
106
107 strcpy (ctx.radix_fmt, "%u");
108 } else if (ctx.flags & F_RADSDECIMAL) {
109
110 strcpy (ctx.radix_fmt, "%d");
111 } else {
112
113 strcpy (ctx.radix_fmt, "0x%x");
114 }
115
116 if (ctx.virtual == 0) {
117 ctx.virtual = memaddr;
118 }
119#ifdef USE_SOURCE_CODE
120 if (ctx.flags & F_SYMBOL) {
121 if (symByAddr == 0)
122 ctx.flags &= ~F_SYMBOL;
123 else {
124 cursym = (char *) 0;
125 symoffset = 0;
126 }
127 }
128#endif
129
130
131
132
133
134
135
136
137 for (i = 0; i < num_instr; ++i, memaddr += 4, ctx.virtual += 4) {
138#ifdef USE_SOURCE_CODE
139 if (ctx.flags & F_LINENO) {
140 if ((line_info_from_addr ((Elf32_Word) ctx.virtual, filename,
141 funcname, &line_no) == TRUE) &&
142 ((line_no != last_line_no) ||
143 (strcmp (last_funcname, funcname) != 0))) {
144 print_source_line (filename, funcname, line_no, pfunc);
145 }
146 last_line_no = line_no;
147 strcpy (last_funcname, funcname);
148 }
149#endif
150
151 sprintf (ctx.data, "%08lx: ", (unsigned long) ctx.virtual);
152 ctx.datalen = 10;
153
154#ifdef USE_SOURCE_CODE
155 if (ctx.flags & F_SYMBOL) {
156 if ((symname =
157 symbol_name_from_addr ((Elf32_Word) ctx.virtual,
158 TRUE, 0)) != 0) {
159 cursym = symname;
160 symoffset = 0;
161 } else {
162 if ((cursym == 0) &&
163 ((symname =
164 symbol_name_from_addr ((Elf32_Word) ctx.virtual,
165 FALSE, &symoffset)) != 0)) {
166 cursym = symname;
167 } else {
168 symoffset += 4;
169 }
170 }
171
172 if (cursym != 0) {
173 sprintf (&ctx.data[ctx.datalen], "<%s+", cursym);
174 ctx.datalen = strlen (ctx.data);
175 sprintf (&ctx.data[ctx.datalen], ctx.radix_fmt, symoffset);
176 strcat (ctx.data, ">");
177 ctx.datalen = strlen (ctx.data);
178 }
179 }
180#endif
181
182 ctx.instr = INSTRUCTION (memaddr);
183
184 if (ctx.flags & F_INSTR) {
185
186
187 sprintf (&ctx.data[ctx.datalen],
188 " %02lx %02lx %02lx %02lx ",
189 ((ctx.instr >> 24) & 0xff),
190 ((ctx.instr >> 16) & 0xff), ((ctx.instr >> 8) & 0xff),
191 (ctx.instr & 0xff));
192 ctx.datalen += 18;
193 } else {
194 strcat (ctx.data, " ");
195 ctx.datalen += 3;
196 }
197
198 if ((ctx.op = find_opcode (ctx.instr)) == 0) {
199
200 sprintf (&ctx.data[ctx.datalen], " .long 0x%08lx",
201 ctx.instr);
202 ctx.datalen += 24;
203 (*pfunc) (ctx.data);
204 continue;
205 }
206
207 if (((ctx.flags & F_SIMPLE) == 0) ||
208 (ctx.op->hfunc == 0) || ((*ctx.op->hfunc) (&ctx) == FALSE)) {
209 sprintf (&ctx.data[ctx.datalen], "%-7s ", ctx.op->name);
210 ctx.datalen += 8;
211 print_operands (&ctx);
212 }
213
214 (*pfunc) (ctx.data);
215 }
216
217 return TRUE;
218}
219
220
221
222
223
224
225
226
227
228
229
230
231int print_operands (struct ppc_ctx *ctx)
232{
233 int open_parens = 0;
234 int field;
235 unsigned long operand;
236 struct operand *opr;
237
238#ifdef USE_SOURCE_CODE
239 char *symname;
240 int offset;
241#endif
242
243
244
245 for (field = 0; ctx->op->fields[field] != 0; ++field) {
246 if (ctx->op->fields[field] > n_operands) {
247 continue;
248 }
249
250 opr = &operands[ctx->op->fields[field] - 1];
251
252 if (opr->hint & OH_SILENT) {
253 continue;
254 }
255
256 if ((field > 0) && !open_parens) {
257 strcat (ctx->data, ",");
258 ctx->datalen++;
259 }
260
261 operand = (ctx->instr >> opr->shift) & ((1 << opr->bits) - 1);
262
263 if (opr->hint & OH_ADDR) {
264 if ((operand & (1 << (opr->bits - 1))) != 0) {
265 operand = operand - (1 << opr->bits);
266 }
267
268 if (ctx->op->hint & H_RELATIVE)
269 operand = (operand << 2) + (unsigned long) ctx->virtual;
270 else
271 operand = (operand << 2);
272
273
274 sprintf (&ctx->data[ctx->datalen], "0x%lx", operand);
275 ctx->datalen = strlen (ctx->data);
276
277#ifdef USE_SOURCE_CODE
278 if ((ctx->flags & F_SYMBOL) &&
279 ((symname =
280 symbol_name_from_addr (operand, 0, &offset)) != 0)) {
281 sprintf (&ctx->data[ctx->datalen], " <%s", symname);
282 if (offset != 0) {
283 strcat (ctx->data, "+");
284 ctx->datalen = strlen (ctx->data);
285 sprintf (&ctx->data[ctx->datalen], ctx->radix_fmt,
286 offset);
287 }
288 strcat (ctx->data, ">");
289 }
290#endif
291 }
292
293 else if (opr->hint & OH_REG) {
294 if ((operand == 0) &&
295 (opr->field == O_rA) && (ctx->op->hint & H_RA0_IS_0)) {
296 strcat (ctx->data, "0");
297 } else {
298 sprintf (&ctx->data[ctx->datalen], "r%d", (short) operand);
299 }
300
301 if (open_parens) {
302 strcat (ctx->data, ")");
303 open_parens--;
304 }
305 }
306
307 else if (opr->hint & OH_SPR) {
308 strcat (ctx->data, spr_name (operand));
309 }
310
311 else if (opr->hint & OH_TBR) {
312 strcat (ctx->data, tbr_name (operand));
313 }
314
315 else if (opr->hint & OH_LITERAL) {
316 switch (opr->field) {
317 case O_cr2:
318 strcat (ctx->data, "cr2");
319 ctx->datalen += 3;
320 break;
321
322 default:
323 break;
324 }
325 }
326
327 else {
328 sprintf (&ctx->data[ctx->datalen], ctx->radix_fmt,
329 (unsigned short) operand);
330
331 if (open_parens) {
332 strcat (ctx->data, ")");
333 open_parens--;
334 }
335
336 else if (opr->hint & OH_OFFSET) {
337 strcat (ctx->data, "(");
338 open_parens++;
339 }
340 }
341
342 ctx->datalen = strlen (ctx->data);
343 }
344
345 return 0;
346}
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373int get_operand_value (struct opcode *op, unsigned long instr,
374 enum OP_FIELD field, unsigned long *value)
375{
376 int i;
377 struct operand *opr;
378
379
380
381 if (field > n_operands) {
382 return FALSE;
383 }
384
385
386 for (i = 0; op->fields[i] != 0; ++i) {
387 if (op->fields[i] != field) {
388 continue;
389 }
390
391 opr = &operands[op->fields[i] - 1];
392
393 if (value) {
394 *value = (instr >> opr->shift) & ((1 << opr->bits) - 1);
395 }
396 return TRUE;
397 }
398
399 return FALSE;
400}
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417struct opcode *find_opcode (unsigned long instr)
418{
419 struct opcode *ptr;
420 int top = 0;
421 int bottom = n_opcodes - 1;
422 int idx;
423
424
425
426 while (top <= bottom) {
427 idx = (top + bottom) >> 1;
428 ptr = &opcodes[idx];
429
430 if ((instr & ptr->mask) < ptr->opcode) {
431 bottom = idx - 1;
432 } else if ((instr & ptr->mask) > ptr->opcode) {
433 top = idx + 1;
434 } else {
435 return ptr;
436 }
437 }
438
439 return (struct opcode *) 0;
440}
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458struct opcode *find_opcode_by_name (char *name)
459{
460 int idx;
461
462
463
464 downstring (name);
465
466 for (idx = 0; idx < n_opcodes; ++idx) {
467 if (!strcmp (name, opcodes[idx].name))
468 return &opcodes[idx];
469 }
470
471 return (struct opcode *) 0;
472}
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490char *spr_name (int value)
491{
492 unsigned short spr;
493 static char other[10];
494 int i;
495
496
497
498
499
500
501 spr = ((value >> 5) & 0x1f) | ((value & 0x1f) << 5);
502
503 for (i = 0; i < n_sprs; ++i) {
504 if (spr == spr_map[i].spr_val)
505 return spr_map[i].spr_name;
506 }
507
508 sprintf (other, "%d", spr);
509 return other;
510}
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526int spr_value (char *name)
527{
528 struct spr_info *sprp;
529 int spr;
530 int i;
531
532
533
534 if (!name || !*name)
535 return 0;
536
537 if (isdigit ((int) name[0])) {
538 i = htonl (read_number (name));
539 spr = ((i >> 5) & 0x1f) | ((i & 0x1f) << 5);
540 return spr;
541 }
542
543 downstring (name);
544
545 for (i = 0; i < n_sprs; ++i) {
546 sprp = &spr_map[i];
547
548 if (strcmp (name, sprp->spr_name) == 0) {
549
550
551 i = htonl (sprp->spr_val);
552 spr = ((i >> 5) & 0x1f) | ((i & 0x1f) << 5);
553
554 return spr;
555 }
556 }
557
558 return 0;
559}
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577char *tbr_name (int value)
578{
579 unsigned short tbr;
580
581
582
583
584
585
586 tbr = ((value >> 5) & 0x1f) | ((value & 0x1f) << 5);
587
588 if (tbr == 268)
589 return "TBL";
590
591 else if (tbr == 269)
592 return "TBU";
593
594
595 return "???";
596}
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611int tbr_value (char *name)
612{
613 int tbr;
614 int val;
615
616
617
618 if (!name || !*name)
619 return 0;
620
621 downstring (name);
622
623 if (isdigit ((int) name[0])) {
624 val = read_number (name);
625
626 if (val != 268 && val != 269)
627 return 0;
628 } else if (strcmp (name, "tbl") == 0)
629 val = 268;
630 else if (strcmp (name, "tbu") == 0)
631 val = 269;
632 else
633 return 0;
634
635
636
637
638 val = htonl (val);
639 tbr = ((val >> 5) & 0x1f) | ((val & 0x1f) << 5);
640 return tbr;
641}
642
643
644
645
646
647
648
649
650
651
652
653
654
655int handle_bc (struct ppc_ctx *ctx)
656{
657 unsigned long bo;
658 unsigned long bi;
659 static struct opcode blt = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0},
660 0, "blt", H_RELATIVE
661 };
662 static struct opcode bne =
663 { B_OPCODE (16, 0, 0), B_MASK, {O_cr2, O_BD, 0},
664 0, "bne", H_RELATIVE
665 };
666 static struct opcode bdnz = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0},
667 0, "bdnz", H_RELATIVE
668 };
669
670
671
672 if (get_operand_value (ctx->op, ctx->instr, O_BO, &bo) == FALSE)
673 return FALSE;
674
675 if (get_operand_value (ctx->op, ctx->instr, O_BI, &bi) == FALSE)
676 return FALSE;
677
678 if ((bo == 12) && (bi == 0)) {
679 ctx->op = &blt;
680 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
681 ctx->datalen += 8;
682 print_operands (ctx);
683 return TRUE;
684 } else if ((bo == 4) && (bi == 10)) {
685 ctx->op = =⃥
686 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
687 ctx->datalen += 8;
688 print_operands (ctx);
689 return TRUE;
690 } else if ((bo == 16) && (bi == 0)) {
691 ctx->op = &bdnz;
692 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
693 ctx->datalen += 8;
694 print_operands (ctx);
695 return TRUE;
696 }
697
698 return FALSE;
699}
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726int print_source_line (char *filename, char *funcname,
727 int line_no, int (*pfunc) (const char *))
728{
729 char out_buf[256];
730
731
732
733 (*pfunc) ("");
734 sprintf (out_buf, "%s %s(): line %d", filename, funcname, line_no);
735 (*pfunc) (out_buf);
736
737 return TRUE;
738}
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753unsigned long asmppc (unsigned long memaddr, char *asm_buf, int *err)
754{
755 struct opcode *opc;
756 struct operand *oper[MAX_OPERANDS];
757 unsigned long instr;
758 unsigned long param;
759 char *ptr = asm_buf;
760 char scratch[20];
761 int i;
762 int w_operands = 0;
763 int n_operands = 0;
764 int asm_debug = 0;
765
766
767
768 if (err)
769 *err = 0;
770
771 if (get_word (&ptr, scratch) == 0)
772 return 0;
773
774
775 if ((opc = find_opcode_by_name (scratch)) == (struct opcode *) 0) {
776 if (err)
777 *err = E_ASM_BAD_OPCODE;
778 return 0;
779 }
780
781 if (asm_debug) {
782 printf ("asmppc: Opcode = \"%s\"\n", opc->name);
783 }
784
785 for (i = 0; i < 8; ++i) {
786 if (opc->fields[i] == 0)
787 break;
788 ++w_operands;
789 }
790
791 if (asm_debug) {
792 printf ("asmppc: Expecting %d operands\n", w_operands);
793 }
794
795 instr = opc->opcode;
796
797
798 while (n_operands < w_operands) {
799
800 oper[n_operands] = &operands[opc->fields[n_operands] - 1];
801
802 if (oper[n_operands]->hint & OH_SILENT) {
803
804
805 if (asm_debug) {
806 printf ("asmppc: Operand %d \"%s\" SILENT\n", n_operands,
807 oper[n_operands]->name);
808 }
809
810 ++n_operands;
811 continue;
812 }
813
814 if (get_word (&ptr, scratch) == 0)
815 break;
816
817 if (asm_debug) {
818 printf ("asmppc: Operand %d \"%s\" : \"%s\"\n", n_operands,
819 oper[n_operands]->name, scratch);
820 }
821
822 if ((param = parse_operand (memaddr, opc, oper[n_operands],
823 scratch, err)) == -1)
824 return 0;
825
826 instr |= param;
827 ++n_operands;
828 }
829
830 if (n_operands < w_operands) {
831 if (err)
832 *err = E_ASM_NUM_OPERANDS;
833 return 0;
834 }
835
836 if (asm_debug) {
837 printf ("asmppc: Instruction = 0x%08lx\n", instr);
838 }
839
840 return instr;
841}
842
843
844
845
846
847
848
849
850
851
852
853
854int parse_operand (unsigned long memaddr, struct opcode *opc,
855 struct operand *oper, char *txt, int *err)
856{
857 long data;
858 long mask;
859 int is_neg = 0;
860
861
862
863 mask = (1 << oper->bits) - 1;
864
865 if (oper->hint & OH_ADDR) {
866 data = read_number (txt);
867
868 if (opc->hint & H_RELATIVE)
869 data = data - memaddr;
870
871 if (data < 0)
872 is_neg = 1;
873
874 data >>= 2;
875 data &= (mask >> 1);
876
877 if (is_neg)
878 data |= 1 << (oper->bits - 1);
879 }
880
881 else if (oper->hint & OH_REG) {
882 if (txt[0] == 'r' || txt[0] == 'R')
883 txt++;
884 else if (txt[0] == '%' && (txt[1] == 'r' || txt[1] == 'R'))
885 txt += 2;
886
887 data = read_number (txt);
888 if (data > 31) {
889 if (err)
890 *err = E_ASM_BAD_REGISTER;
891 return -1;
892 }
893
894 data = htonl (data);
895 }
896
897 else if (oper->hint & OH_SPR) {
898 if ((data = spr_value (txt)) == 0) {
899 if (err)
900 *err = E_ASM_BAD_SPR;
901 return -1;
902 }
903 }
904
905 else if (oper->hint & OH_TBR) {
906 if ((data = tbr_value (txt)) == 0) {
907 if (err)
908 *err = E_ASM_BAD_TBR;
909 return -1;
910 }
911 }
912
913 else {
914 data = htonl (read_number (txt));
915 }
916
917 return (data & mask) << oper->shift;
918}
919
920
921char *asm_error_str (int err)
922{
923 switch (err) {
924 case E_ASM_BAD_OPCODE:
925 return "Bad opcode";
926 case E_ASM_NUM_OPERANDS:
927 return "Bad number of operands";
928 case E_ASM_BAD_REGISTER:
929 return "Bad register number";
930 case E_ASM_BAD_SPR:
931 return "Bad SPR name or number";
932 case E_ASM_BAD_TBR:
933 return "Bad TBR name or number";
934 }
935
936 return "";
937}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953int get_word (char **src, char *dest)
954{
955 char *ptr = *src;
956 int nchars = 0;
957
958
959
960
961 while (*ptr && isblank (*ptr))
962 ptr++;
963
964 if (*ptr == 0) {
965 *src = ptr;
966 return 0;
967 }
968
969
970 while (*ptr && !isblank (*ptr) && (*ptr != ','))
971 dest[nchars++] = *ptr++;
972 ptr = (*ptr == ',') ? ptr + 1 : ptr;
973 dest[nchars] = 0;
974
975 *src = ptr;
976 return nchars;
977}
978
979
980
981
982
983
984
985
986
987
988
989
990long read_number (char *txt)
991{
992 long val;
993 int is_neg = 0;
994
995
996
997 if (txt == 0 || *txt == 0)
998 return 0;
999
1000 if (*txt == '-') {
1001 is_neg = 1;
1002 ++txt;
1003 }
1004
1005 if (txt[0] == '0' && (txt[1] == 'x' || txt[1] == 'X'))
1006 val = simple_strtoul (&txt[2], NULL, 16);
1007 else
1008 val = simple_strtoul (txt, NULL, 10);
1009
1010 if (is_neg)
1011 val = -val;
1012
1013 return val;
1014}
1015
1016
1017int downstring (char *s)
1018{
1019 if (!s || !*s)
1020 return 0;
1021
1022 while (*s) {
1023 if (isupper (*s))
1024 *s = tolower (*s);
1025 s++;
1026 }
1027
1028 return 0;
1029}
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053int find_next_address (unsigned char *nextaddr, int step_over,
1054 struct pt_regs *regs)
1055{
1056 unsigned long pc;
1057 unsigned long ctr;
1058 unsigned long cr;
1059 unsigned long lr;
1060 unsigned long instr;
1061 unsigned long next;
1062 unsigned long step;
1063 unsigned long addr = 0;
1064 unsigned long aa = 0;
1065 unsigned long lk = 0;
1066 unsigned long bo = 0;
1067 unsigned long bi = 0;
1068 struct opcode *op = 0;
1069 int ctr_ok = 0;
1070 int cond_ok = 0;
1071 int conditional = 0;
1072 int branch = 0;
1073
1074
1075
1076 if (nextaddr == 0 || regs == 0) {
1077 printf ("find_next_address: bad args");
1078 return FALSE;
1079 }
1080
1081 pc = regs->nip & 0xfffffffc;
1082 instr = INSTRUCTION (pc);
1083
1084 if ((op = find_opcode (instr)) == (struct opcode *) 0) {
1085 printf ("find_next_address: can't parse opcode 0x%lx", instr);
1086 return FALSE;
1087 }
1088
1089 ctr = regs->ctr;
1090 cr = regs->ccr;
1091 lr = regs->link;
1092
1093 switch (op->opcode) {
1094 case B_OPCODE (16, 0, 0):
1095 case B_OPCODE (16, 0, 1):
1096 case B_OPCODE (16, 1, 0):
1097 case B_OPCODE (16, 1, 1):
1098 if (!get_operand_value (op, instr, O_BD, &addr) ||
1099 !get_operand_value (op, instr, O_BO, &bo) ||
1100 !get_operand_value (op, instr, O_BI, &bi) ||
1101 !get_operand_value (op, instr, O_AA, &aa) ||
1102 !get_operand_value (op, instr, O_LK, &lk))
1103 return FALSE;
1104
1105 if ((addr & (1 << 13)) != 0)
1106 addr = addr - (1 << 14);
1107 addr <<= 2;
1108 conditional = 1;
1109 branch = 1;
1110 break;
1111
1112 case I_OPCODE (18, 0, 0):
1113 case I_OPCODE (18, 0, 1):
1114 case I_OPCODE (18, 1, 0):
1115 case I_OPCODE (18, 1, 1):
1116 if (!get_operand_value (op, instr, O_LI, &addr) ||
1117 !get_operand_value (op, instr, O_AA, &aa) ||
1118 !get_operand_value (op, instr, O_LK, &lk))
1119 return FALSE;
1120
1121 if ((addr & (1 << 23)) != 0)
1122 addr = addr - (1 << 24);
1123 addr <<= 2;
1124 conditional = 0;
1125 branch = 1;
1126 break;
1127
1128 case XL_OPCODE (19, 528, 0):
1129 case XL_OPCODE (19, 528, 1):
1130 if (!get_operand_value (op, instr, O_BO, &bo) ||
1131 !get_operand_value (op, instr, O_BI, &bi) ||
1132 !get_operand_value (op, instr, O_LK, &lk))
1133 return FALSE;
1134
1135 addr = ctr;
1136 aa = 1;
1137 conditional = 1;
1138 branch = 1;
1139 break;
1140
1141 case XL_OPCODE (19, 16, 0):
1142 case XL_OPCODE (19, 16, 1):
1143 if (!get_operand_value (op, instr, O_BO, &bo) ||
1144 !get_operand_value (op, instr, O_BI, &bi) ||
1145 !get_operand_value (op, instr, O_LK, &lk))
1146 return FALSE;
1147
1148 addr = lr;
1149 aa = 1;
1150 conditional = 1;
1151 branch = 1;
1152 break;
1153
1154 default:
1155 conditional = 0;
1156 branch = 0;
1157 break;
1158 }
1159
1160 if (conditional) {
1161 switch ((bo & 0x1e) >> 1) {
1162 case 0:
1163 if (--ctr != 0)
1164 ctr_ok = 1;
1165
1166 cond_ok = !(cr & (1 << (31 - bi)));
1167 break;
1168
1169 case 1:
1170 if (--ctr == 0)
1171 ctr_ok = 1;
1172
1173 cond_ok = !(cr & (1 << (31 - bi)));
1174 break;
1175
1176 case 2:
1177 ctr_ok = 1;
1178 cond_ok = !(cr & (1 << (31 - bi)));
1179 break;
1180
1181 case 4:
1182 if (--ctr != 0)
1183 ctr_ok = 1;
1184
1185 cond_ok = cr & (1 << (31 - bi));
1186 break;
1187
1188 case 5:
1189 if (--ctr == 0)
1190 ctr_ok = 1;
1191
1192 cond_ok = cr & (1 << (31 - bi));
1193 break;
1194
1195 case 6:
1196 ctr_ok = 1;
1197 cond_ok = cr & (1 << (31 - bi));
1198 break;
1199
1200 case 8:
1201 if (--ctr != 0)
1202 ctr_ok = cond_ok = 1;
1203 break;
1204
1205 case 9:
1206 if (--ctr == 0)
1207 ctr_ok = cond_ok = 1;
1208 break;
1209
1210 case 10:
1211 ctr_ok = cond_ok = 1;
1212 break;
1213 }
1214 }
1215
1216 if (branch && (!conditional || (ctr_ok && cond_ok))) {
1217 if (aa)
1218 step = addr;
1219 else
1220 step = addr + pc;
1221
1222 if (lk)
1223 next = pc + 4;
1224 else
1225 next = step;
1226 } else {
1227 step = next = pc + 4;
1228 }
1229
1230 if (step_over == TRUE)
1231 *(unsigned long *) nextaddr = next;
1232 else
1233 *(unsigned long *) nextaddr = step;
1234
1235 return TRUE;
1236}
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253