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, ®.ctr, 1); 128 } 129 130 void 131 bclr(ulong ir) 132 { 133 dobranch(ir, ®.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 } 273