]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/qi/branch.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / qi / branch.c
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 *
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 *
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
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
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
125 bcctr(ulong ir)
126 {
127         dobranch(ir, &reg.ctr, 1);
128 }
129
130 void
131 bclr(ulong ir)
132 {
133         dobranch(ir, &reg.lr, 0);
134 }
135
136 void
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
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
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
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
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
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
267 isync(ulong ir)
268 {
269         USED(ir);
270         if(trace)
271                 itrace("isync");
272 }