LEFT | RIGHT |
(no file at all) | |
1 // Inferno utils/5l/asm.c | 1 // Inferno utils/5l/asm.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c |
3 // | 3 // |
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) |
6 // Portions Copyright © 1997-1999 Vita Nuova Limited | 6 // Portions Copyright © 1997-1999 Vita Nuova Limited |
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) | 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) |
8 // Portions Copyright © 2004,2006 Bruce Ellis | 8 // Portions Copyright © 2004,2006 Bruce Ellis |
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) |
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 static void addgotsyminternal(Sym*); | 86 static void addgotsyminternal(Sym*); |
87 | 87 |
88 // Preserve highest 8 bits of a, and do addition to lower 24-bit | 88 // Preserve highest 8 bits of a, and do addition to lower 24-bit |
89 // of a and b; used to adjust ARM branch intruction's target | 89 // of a and b; used to adjust ARM branch intruction's target |
90 static int32 | 90 static int32 |
91 braddoff(int32 a, int32 b) | 91 braddoff(int32 a, int32 b) |
92 { | 92 { |
93 return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b)); | 93 return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b)); |
94 } | 94 } |
95 | 95 |
| 96 Sym * |
| 97 lookuprel(void) |
| 98 { |
| 99 return lookup(".rel", 0); |
| 100 } |
| 101 |
| 102 void |
| 103 adddynrela(Sym *rel, Sym *s, Reloc *r) |
| 104 { |
| 105 addaddrplus(rel, s, r->off); |
| 106 adduint32(rel, R_ARM_RELATIVE); |
| 107 } |
| 108 |
96 void | 109 void |
97 adddynrel(Sym *s, Reloc *r) | 110 adddynrel(Sym *s, Reloc *r) |
98 { | 111 { |
99 Sym *targ, *rel; | 112 Sym *targ, *rel; |
100 | 113 |
101 targ = r->sym; | 114 targ = r->sym; |
102 cursym = s; | 115 cursym = s; |
103 | 116 |
104 switch(r->type) { | 117 switch(r->type) { |
105 default: | 118 default: |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
852 } | 865 } |
853 break; | 866 break; |
854 | 867 |
855 case 11: /* word */ | 868 case 11: /* word */ |
856 aclass(&p->to); | 869 aclass(&p->to); |
857 o1 = instoffset; | 870 o1 = instoffset; |
858 if(p->to.sym != S) { | 871 if(p->to.sym != S) { |
859 rel = addrel(cursym); | 872 rel = addrel(cursym); |
860 rel->off = pc - cursym->value; | 873 rel->off = pc - cursym->value; |
861 rel->siz = 4; | 874 rel->siz = 4; |
862 rel->type = D_ADDR; | |
863 rel->sym = p->to.sym; | 875 rel->sym = p->to.sym; |
864 rel->add = p->to.offset; | 876 rel->add = p->to.offset; |
| 877 if(flag_shared) { |
| 878 rel->type = D_PCREL; |
| 879 rel->add += pc - p->pcrel->pc - 8; |
| 880 } else |
| 881 rel->type = D_ADDR; |
865 o1 = 0; | 882 o1 = 0; |
866 } | 883 } |
867 break; | 884 break; |
868 | 885 |
869 case 12: /* movw $lcon, reg */ | 886 case 12: /* movw $lcon, reg */ |
870 o1 = omvl(p, &p->from, p->to.reg); | 887 o1 = omvl(p, &p->from, p->to.reg); |
| 888 if(o->flag & LPCREL) { |
| 889 o2 = oprrr(AADD, p->scond) | p->to.reg | REGPC << 16 | p
->to.reg << 12; |
| 890 } |
871 break; | 891 break; |
872 | 892 |
873 case 13: /* op $lcon, [R], R */ | 893 case 13: /* op $lcon, [R], R */ |
874 o1 = omvl(p, &p->from, REGTMP); | 894 o1 = omvl(p, &p->from, REGTMP); |
875 if(!o1) | 895 if(!o1) |
876 break; | 896 break; |
877 o2 = oprrr(p->as, p->scond); | 897 o2 = oprrr(p->as, p->scond); |
878 o2 |= REGTMP; | 898 o2 |= REGTMP; |
879 r = p->reg; | 899 r = p->reg; |
880 if(p->as == AMOVW || p->as == AMVN) | 900 if(p->as == AMOVW || p->as == AMVN) |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 | 1185 |
1166 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ | 1186 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ |
1167 if(p->to.reg == NREG) | 1187 if(p->to.reg == NREG) |
1168 diag("MOV to shifter operand"); | 1188 diag("MOV to shifter operand"); |
1169 o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond); | 1189 o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond); |
1170 if(p->as == AMOVB || p->as == AMOVBU) | 1190 if(p->as == AMOVB || p->as == AMOVBU) |
1171 o1 |= 1<<22; | 1191 o1 |= 1<<22; |
1172 break; | 1192 break; |
1173 | 1193 |
1174 case 62: /* case R -> movw R<<2(PC),PC */ | 1194 case 62: /* case R -> movw R<<2(PC),PC */ |
1175 » » o1 = olrr(p->from.reg, REGPC, REGPC, p->scond); | 1195 » » if(o->flag & LPCREL) { |
1176 » » o1 |= 2<<7; | 1196 » » » o1 = oprrr(AADD, p->scond) | immrot(1) | p->from.reg <<
16 | REGTMP << 12; |
| 1197 » » » o2 = olrr(REGTMP, REGPC, REGTMP, p->scond); |
| 1198 » » » o2 |= 2<<7; |
| 1199 » » » o3 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGP
C << 12; |
| 1200 » » } else { |
| 1201 » » » o1 = olrr(p->from.reg, REGPC, REGPC, p->scond); |
| 1202 » » » o1 |= 2<<7; |
| 1203 » » } |
1177 break; | 1204 break; |
1178 | 1205 |
1179 case 63: /* bcase */ | 1206 case 63: /* bcase */ |
1180 » » if(p->cond != P) | 1207 » » if(p->cond != P) { |
1181 o1 = p->cond->pc; | 1208 o1 = p->cond->pc; |
| 1209 if(flag_shared) |
| 1210 o1 = o1 - p->pcrel->pc - 16; |
| 1211 } |
1182 break; | 1212 break; |
1183 | 1213 |
1184 /* reloc ops */ | 1214 /* reloc ops */ |
1185 case 64: /* mov/movb/movbu R,addr */ | 1215 case 64: /* mov/movb/movbu R,addr */ |
1186 o1 = omvl(p, &p->to, REGTMP); | 1216 o1 = omvl(p, &p->to, REGTMP); |
1187 if(!o1) | 1217 if(!o1) |
1188 break; | 1218 break; |
1189 o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); | 1219 o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); |
| 1220 if(o->flag & LPCREL) { |
| 1221 o3 = o2; |
| 1222 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1223 } |
1190 break; | 1224 break; |
1191 | 1225 |
1192 case 65: /* mov/movbu addr,R */ | 1226 case 65: /* mov/movbu addr,R */ |
1193 o1 = omvl(p, &p->from, REGTMP); | 1227 o1 = omvl(p, &p->from, REGTMP); |
1194 if(!o1) | 1228 if(!o1) |
1195 break; | 1229 break; |
1196 o2 = olr(0, REGTMP, p->to.reg, p->scond); | 1230 o2 = olr(0, REGTMP, p->to.reg, p->scond); |
1197 if(p->as == AMOVBU || p->as == AMOVB) | 1231 if(p->as == AMOVBU || p->as == AMOVB) |
1198 o2 |= 1<<22; | 1232 o2 |= 1<<22; |
| 1233 if(o->flag & LPCREL) { |
| 1234 o3 = o2; |
| 1235 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1236 } |
1199 break; | 1237 break; |
1200 | 1238 |
1201 case 68: /* floating point store -> ADDR */ | 1239 case 68: /* floating point store -> ADDR */ |
1202 o1 = omvl(p, &p->to, REGTMP); | 1240 o1 = omvl(p, &p->to, REGTMP); |
1203 if(!o1) | 1241 if(!o1) |
1204 break; | 1242 break; |
1205 o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); | 1243 o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); |
| 1244 if(o->flag & LPCREL) { |
| 1245 o3 = o2; |
| 1246 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1247 } |
1206 break; | 1248 break; |
1207 | 1249 |
1208 case 69: /* floating point load <- ADDR */ | 1250 case 69: /* floating point load <- ADDR */ |
1209 o1 = omvl(p, &p->from, REGTMP); | 1251 o1 = omvl(p, &p->from, REGTMP); |
1210 if(!o1) | 1252 if(!o1) |
1211 break; | 1253 break; |
1212 o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); | 1254 o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); |
| 1255 if(o->flag & LPCREL) { |
| 1256 o3 = o2; |
| 1257 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1258 } |
1213 break; | 1259 break; |
1214 | 1260 |
1215 /* ArmV4 ops: */ | 1261 /* ArmV4 ops: */ |
1216 case 70: /* movh/movhu R,O(R) -> strh */ | 1262 case 70: /* movh/movhu R,O(R) -> strh */ |
1217 aclass(&p->to); | 1263 aclass(&p->to); |
1218 r = p->to.reg; | 1264 r = p->to.reg; |
1219 if(r == NREG) | 1265 if(r == NREG) |
1220 r = o->param; | 1266 r = o->param; |
1221 o1 = oshr(p->from.reg, instoffset, r, p->scond); | 1267 o1 = oshr(p->from.reg, instoffset, r, p->scond); |
1222 break; | 1268 break; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1399 break; | 1445 break; |
1400 case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ | 1446 case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ |
1401 o1 = omvl(p, &p->from, REGTMP); | 1447 o1 = omvl(p, &p->from, REGTMP); |
1402 if(!o1) | 1448 if(!o1) |
1403 break; | 1449 break; |
1404 o2 = olhr(0, REGTMP, p->to.reg, p->scond); | 1450 o2 = olhr(0, REGTMP, p->to.reg, p->scond); |
1405 if(p->as == AMOVB) | 1451 if(p->as == AMOVB) |
1406 o2 ^= (1<<5)|(1<<6); | 1452 o2 ^= (1<<5)|(1<<6); |
1407 else if(p->as == AMOVH) | 1453 else if(p->as == AMOVH) |
1408 o2 ^= (1<<6); | 1454 o2 ^= (1<<6); |
| 1455 if(o->flag & LPCREL) { |
| 1456 o3 = o2; |
| 1457 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1458 } |
1409 break; | 1459 break; |
1410 case 94: /* movh/movhu R,addr -> strh */ | 1460 case 94: /* movh/movhu R,addr -> strh */ |
1411 o1 = omvl(p, &p->to, REGTMP); | 1461 o1 = omvl(p, &p->to, REGTMP); |
1412 if(!o1) | 1462 if(!o1) |
1413 break; | 1463 break; |
1414 o2 = oshr(p->from.reg, 0, REGTMP, p->scond); | 1464 o2 = oshr(p->from.reg, 0, REGTMP, p->scond); |
| 1465 if(o->flag & LPCREL) { |
| 1466 o3 = o2; |
| 1467 o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGT
MP << 12; |
| 1468 } |
1415 break; | 1469 break; |
1416 case 95: /* PLD off(reg) */ | 1470 case 95: /* PLD off(reg) */ |
1417 o1 = 0xf5d0f000; | 1471 o1 = 0xf5d0f000; |
1418 o1 |= p->from.reg << 16; | 1472 o1 |= p->from.reg << 16; |
1419 if(p->from.offset < 0) { | 1473 if(p->from.offset < 0) { |
1420 o1 &= ~(1 << 23); | 1474 o1 &= ~(1 << 23); |
1421 o1 |= (-p->from.offset) & 0xfff; | 1475 o1 |= (-p->from.offset) & 0xfff; |
1422 } else | 1476 } else |
1423 o1 |= p->from.offset & 0xfff; | 1477 o1 |= p->from.offset & 0xfff; |
1424 break; | 1478 break; |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1857 | 1911 |
1858 // rest of exp and mantissa (cd-efgh) | 1912 // rest of exp and mantissa (cd-efgh) |
1859 n |= (e->h >> 16) & 0x3f; | 1913 n |= (e->h >> 16) & 0x3f; |
1860 | 1914 |
1861 //print("match %.8lux %.8lux %d\n", e->l, e->h, n); | 1915 //print("match %.8lux %.8lux %d\n", e->l, e->h, n); |
1862 return n; | 1916 return n; |
1863 | 1917 |
1864 no: | 1918 no: |
1865 return -1; | 1919 return -1; |
1866 } | 1920 } |
LEFT | RIGHT |