1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern extern
6 #include "power.h"
7
8 void mcrf(ulong);
9 void bclr(ulong);
10 void crop(ulong);
11 void bcctr(ulong);
12 void call(ulong);
13 void ret(ulong);
14 void isync(ulong);
15
16 Inst op19[] = {
17 [0] {mcrf, "mcrf", Ibranch},
18 [16] {bclr, "bclr", Ibranch},
19 [33] {crop, "crnor", Ibranch},
20 [15] {0, "rfi", Ibranch},
21 [129] {crop, "crandc", Ibranch},
22 [150] {isync, "isync", Ibranch},
23 [193] {crop, "crxor", Ibranch},
24 [225] {crop, "crnand", Ibranch},
25 [257] {crop, "crand", Ibranch},
26 [289] {crop, "creqv", Ibranch},
27 [417] {crop, "crorc", Ibranch},
28 [449] {crop, "cror", Ibranch},
29 [528] {bcctr, "bcctr", Ibranch},
30 {0, 0, 0}
31 };
32
33 Inset ops19 = {op19, nelem(op19)-1};
34
35 static char *
boname(int bo)36 boname(int bo)
37 {
38 static char buf[8];
39
40 switch(bo>>1){
41 case 0: return "dnzf";
42 case 1: return "dzf";
43 case 2: return "f";
44 case 4: return "dnzt";
45 case 5: return "dzt";
46 case 6: return "t";
47 case 8: return "dnz";
48 case 9: return "dz";
49 case 10: return "a";
50 default:
51 sprint(buf, "%d?", bo);
52 return buf;
53 }
54 }
55
56 static char *
cname(int bo,int bi)57 cname(int bo, int bi)
58 {
59 int f;
60 char *p;
61 static char buf[20];
62 static char *f0[] = {"lt", "gt", "eq", "so/un"};
63
64 if(bo == 0x14){ /* branch always */
65 sprint(buf,"%d", bi);
66 return buf;
67 }
68 for(f = 0; bi >= 4; bi -= 4)
69 f++;
70 p = buf;
71 p += sprint(buf, "%d[", bi);
72 if(f)
73 p += sprint(buf, "cr%d+", f);
74 strcpy(p, f0[bi&3]);
75 strcat(p, "]");
76 return buf;
77 }
78
79 static int
condok(ulong ir,int ctr)80 condok(ulong ir, int ctr)
81 {
82 int bo, bi, xx;
83
84 getbobi(ir);
85 if(xx)
86 undef(ir);
87 if((bo & 0x4) == 0) {
88 if(!ctr)
89 undef(ir);
90 reg.ctr--;
91 }
92 if(bo & 0x4 || (reg.ctr!=0)^((bo>>1)&1)) {
93 if(bo & 0x10 || (((reg.cr & bits[bi])!=0)==((bo>>3)&1)))
94 return 1;
95 }
96 return 0;
97 }
98
99 static void
dobranch(ulong ir,ulong * r,int ctr)100 dobranch(ulong ir, ulong *r, int ctr)
101 {
102 int bo, bi, xx;
103 ulong nia;
104
105 getbobi(ir);
106 USED(xx);
107 if(condok(ir, ctr)) {
108 ci->taken++;
109 nia = *r & ~3;
110 if(bo & 4) /* assume counting branches aren't returns */
111 ret(nia);
112 } else
113 nia = reg.pc + 4;
114 if(trace)
115 itrace("%s%s\t%s,%s,#%.8lux", ci->name, ir&1? "l": "", boname(bo), cname(bo, bi), nia);
116 if(ir & 1) {
117 call(nia);
118 reg.lr = reg.pc + 4;
119 }
120 reg.pc = nia-4;
121 /* branch delays? */
122 }
123
124 void
bcctr(ulong ir)125 bcctr(ulong ir)
126 {
127 dobranch(ir, ®.ctr, 1);
128 }
129
130 void
bclr(ulong ir)131 bclr(ulong ir)
132 {
133 dobranch(ir, ®.lr, 0);
134 }
135
136 void
bcx(ulong ir)137 bcx(ulong ir)
138 {
139 int bo, bi, xx;
140 ulong ea;
141 long imm;
142 static char *opc[] = {"bc", "bcl", "bca", "bcla"};
143
144 getbobi(ir);
145 USED(xx);
146 imm = ir & 0xFFFC;
147 if(ir & 0x08000)
148 imm |= 0xFFFF0000;
149 if((ir & 2) == 0) { /* not absolute address */
150 ea = reg.pc + imm;
151 if(trace)
152 itrace("%s\t%s,%s,.%s%ld\tea = #%.8lux", opc[ir&3], boname(bo), cname(bo, bi), imm<0?"":"+", imm, ea);
153 } else {
154 ea = imm;
155 if(trace)
156 itrace("%s\t%s,%s,#%.8lux", opc[ir&3], boname(bo), cname(bo, bi), ea);
157 }
158 if(condok(ir&0xFFFF0000, 1))
159 ci->taken++;
160 else
161 ea = reg.pc + 4;
162 if(ir & 1) {
163 call(ea);
164 reg.lr = reg.pc+4;
165 }
166 reg.pc = ea-4;
167 /* branch delay? */
168 }
169
170 void
crop(ulong ir)171 crop(ulong ir)
172 {
173 int rd, ra, rb, d;
174
175 getarrr(ir);
176 if(trace)
177 itrace("%s\tcrb%d,crb%d,crb%d", ci->name, rd, ra, rb);
178 ra = (reg.cr & bits[ra]) != 0;
179 rb = (reg.cr & bits[rb]) != 0;
180 d = 0;
181 switch(getxo(ir)) {
182 case 257: d = ra & rb; break;
183 case 129: d = ra & !rb; break;
184 case 289: d = ra == rb; break;
185 case 225: d = !(ra & rb); break;
186 case 33: d = !(ra | rb); break;
187 case 449: d = ra | rb; break;
188 case 417: d = ra | !rb; break;
189 case 193: d = ra ^ rb; break;
190 default: undef(ir); break;
191 }
192 if(d)
193 reg.cr |= bits[rd];
194 }
195
196 void
mcrf(ulong ir)197 mcrf(ulong ir)
198 {
199 int rd, ra, rb;
200
201 getarrr(ir);
202 if(ir & 1 || rd & 3 || ra & 3 || rb)
203 undef(ir);
204 ra >>= 2;
205 rd >>= 2;
206 reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.cr));
207 if(trace)
208 itrace("mcrf\tcrf%d,crf%d", rd, ra);
209 }
210
211 void
call(ulong npc)212 call(ulong npc)
213 {
214 Symbol s;
215
216 if(calltree) {
217 findsym(npc, CTEXT, &s);
218 Bprint(bioout, "%8lux %s(", reg.pc, s.name);
219 printparams(&s, reg.r[1]);
220 Bprint(bioout, "from ");
221 printsource(reg.pc);
222 Bputc(bioout, '\n');
223 }
224 }
225
226 void
ret(ulong npc)227 ret(ulong npc)
228 {
229 Symbol s;
230
231 if(calltree) {
232 findsym(npc, CTEXT, &s);
233 Bprint(bioout, "%8lux return to #%lux %s r3=#%lux (%ld)\n",
234 reg.pc, npc, s.name, reg.r[3], reg.r[3]);
235 }
236 }
237
238 void
bx(ulong ir)239 bx(ulong ir)
240 {
241 ulong ea;
242 long imm;
243 static char *opc[] = {"b", "bl", "ba", "bla"};
244
245 imm = ir & 0x03FFFFFC;
246 if(ir & 0x02000000)
247 imm |= 0xFC000000;
248 if((ir & 2) == 0) { /* not absolute address */
249 ea = reg.pc + imm;
250 if(trace)
251 itrace("%s\t.%s%ld\tea = #%.8lux", opc[ir&3], imm<0?"":"+", imm, ea);
252 } else {
253 ea = imm;
254 if(trace)
255 itrace("%s\t#%.8lux", opc[ir&3], ea);
256 }
257 ci->taken++;
258 if(ir & 1) {
259 call(ea);
260 reg.lr = reg.pc+4;
261 }
262 reg.pc = ea-4;
263 /* branch delay? */
264 }
265
266 void
isync(ulong ir)267 isync(ulong ir)
268 {
269 USED(ir);
270 if(trace)
271 itrace("isync");
272 }
273