~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

Viewing changes to src/cmd/5l/asm.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include        "l.h"
34
34
#include        "../ld/lib.h"
35
35
#include        "../ld/elf.h"
 
36
#include        "../ld/dwarf.h"
36
37
 
37
38
static Prog *PP;
38
39
 
39
 
char linuxdynld[] = "/lib/ld-linux.so.2";
 
40
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
 
41
char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
 
42
char openbsddynld[] = "XXX";
 
43
char netbsddynld[] = "/libexec/ld.elf_so";
40
44
 
41
45
int32
42
46
entryvalue(void)
55
59
        return s->value;
56
60
}
57
61
 
58
 
enum {
59
 
        ElfStrEmpty,
60
 
        ElfStrInterp,
61
 
        ElfStrHash,
62
 
        ElfStrGot,
63
 
        ElfStrGotPlt,
64
 
        ElfStrDynamic,
65
 
        ElfStrDynsym,
66
 
        ElfStrDynstr,
67
 
        ElfStrRel,
68
 
        ElfStrText,
69
 
        ElfStrData,
70
 
        ElfStrBss,
71
 
        ElfStrSymtab,
72
 
        ElfStrStrtab,
73
 
        ElfStrShstrtab,
74
 
        ElfStrRelPlt,
75
 
        ElfStrPlt,
76
 
        ElfStrNoteNetbsdIdent,
77
 
        ElfStrNoPtrData,
78
 
        ElfStrNoPtrBss,
79
 
        NElfStr
80
 
};
81
 
 
82
 
vlong elfstr[NElfStr];
83
 
 
84
62
static int
85
63
needlib(char *name)
86
64
{
103
81
 
104
82
int     nelfsym = 1;
105
83
 
 
84
static void     addpltsym(Sym*);
 
85
static void     addgotsym(Sym*);
 
86
static void     addgotsyminternal(Sym*);
 
87
 
 
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
 
90
static int32
 
91
braddoff(int32 a, int32 b)
 
92
{
 
93
        return (((uint32)a) & 0xff000000U) | (0x00ffffffU & (uint32)(a + b));
 
94
}
 
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
 
106
109
void
107
110
adddynrel(Sym *s, Reloc *r)
108
111
{
109
 
        USED(s);
110
 
        USED(r);
111
 
        diag("adddynrel: unsupported binary format");
 
112
        Sym *targ, *rel;
 
113
 
 
114
        targ = r->sym;
 
115
        cursym = s;
 
116
 
 
117
        switch(r->type) {
 
118
        default:
 
119
                if(r->type >= 256) {
 
120
                        diag("unexpected relocation type %d", r->type);
 
121
                        return;
 
122
                }
 
123
                break;
 
124
 
 
125
        // Handle relocations found in ELF object files.
 
126
        case 256 + R_ARM_PLT32:
 
127
                r->type = D_CALL;
 
128
                if(targ->type == SDYNIMPORT) {
 
129
                        addpltsym(targ);
 
130
                        r->sym = lookup(".plt", 0);
 
131
                        r->add = braddoff(r->add, targ->plt / 4);
 
132
                }
 
133
                return;
 
134
 
 
135
        case 256 + R_ARM_THM_PC22: // R_ARM_THM_CALL
 
136
                diag("R_ARM_THM_CALL, are you using -marm?");
 
137
                errorexit();
 
138
                return;
 
139
 
 
140
        case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
 
141
                if(targ->type != SDYNIMPORT) {
 
142
                        addgotsyminternal(targ);
 
143
                } else {
 
144
                        addgotsym(targ);
 
145
                }
 
146
                r->type = D_CONST;      // write r->add during relocsym
 
147
                r->sym = S;
 
148
                r->add += targ->got;
 
149
                return;
 
150
 
 
151
        case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
 
152
                if(targ->type != SDYNIMPORT) {
 
153
                        addgotsyminternal(targ);
 
154
                } else {
 
155
                        addgotsym(targ);
 
156
                }
 
157
                r->type = D_PCREL;
 
158
                r->sym = lookup(".got", 0);
 
159
                r->add += targ->got + 4;
 
160
                return;
 
161
 
 
162
        case 256 + R_ARM_GOTOFF: // R_ARM_GOTOFF32
 
163
                r->type = D_GOTOFF;
 
164
                return;
 
165
 
 
166
        case 256 + R_ARM_GOTPC: // R_ARM_BASE_PREL
 
167
                r->type = D_PCREL;
 
168
                r->sym = lookup(".got", 0);
 
169
                r->add += 4;
 
170
                return;
 
171
 
 
172
        case 256 + R_ARM_CALL:
 
173
                r->type = D_CALL;
 
174
                if(targ->type == SDYNIMPORT) {
 
175
                        addpltsym(targ);
 
176
                        r->sym = lookup(".plt", 0);
 
177
                        r->add = braddoff(r->add, targ->plt / 4);
 
178
                }
 
179
                return;
 
180
 
 
181
        case 256 + R_ARM_REL32: // R_ARM_REL32
 
182
                r->type = D_PCREL;
 
183
                r->add += 4;
 
184
                return;
 
185
 
 
186
        case 256 + R_ARM_ABS32: 
 
187
                if(targ->type == SDYNIMPORT)
 
188
                        diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
 
189
                r->type = D_ADDR;
 
190
                return;
 
191
 
 
192
        case 256 + R_ARM_V4BX:
 
193
                // we can just ignore this, because we are targeting ARM V5+ anyway
 
194
                if(r->sym) {
 
195
                        // R_ARM_V4BX is ABS relocation, so this symbol is a dummy symbol, ignore it
 
196
                        r->sym->type = 0;
 
197
                }
 
198
                r->sym = S;
 
199
                return;
 
200
 
 
201
        case 256 + R_ARM_PC24:
 
202
        case 256 + R_ARM_JUMP24:
 
203
                r->type = D_CALL;
 
204
                if(targ->type == SDYNIMPORT) {
 
205
                        addpltsym(targ);
 
206
                        r->sym = lookup(".plt", 0);
 
207
                        r->add = braddoff(r->add, targ->plt / 4);
 
208
                }
 
209
                return;
 
210
        }
 
211
        
 
212
        // Handle references to ELF symbols from our own object files.
 
213
        if(targ->type != SDYNIMPORT)
 
214
                return;
 
215
 
 
216
        switch(r->type) {
 
217
        case D_PCREL:
 
218
                addpltsym(targ);
 
219
                r->sym = lookup(".plt", 0);
 
220
                r->add = targ->plt;
 
221
                return;
 
222
        
 
223
        case D_ADDR:
 
224
                if(s->type != SDATA)
 
225
                        break;
 
226
                if(iself) {
 
227
                        adddynsym(targ);
 
228
                        rel = lookup(".rel", 0);
 
229
                        addaddrplus(rel, s, r->off);
 
230
                        adduint32(rel, ELF32_R_INFO(targ->dynid, R_ARM_GLOB_DAT)); // we need a S + A dynmic reloc
 
231
                        r->type = D_CONST;      // write r->add during relocsym
 
232
                        r->sym = S;
 
233
                        return;
 
234
                }
 
235
                break;
 
236
        }
 
237
 
 
238
        cursym = s;
 
239
        diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
 
240
}
 
241
 
 
242
int
 
243
elfreloc1(Reloc *r, vlong sectoff)
 
244
{
 
245
        int32 elfsym;
 
246
        
 
247
        LPUT(sectoff);
 
248
 
 
249
        elfsym = r->xsym->elfsym;
 
250
        switch(r->type) {
 
251
        default:
 
252
                return -1;
 
253
 
 
254
        case D_ADDR:
 
255
                if(r->siz == 4)
 
256
                        LPUT(R_ARM_ABS32 | elfsym<<8);
 
257
                else
 
258
                        return -1;
 
259
                break;
 
260
 
 
261
        case D_PCREL:
 
262
                if(r->siz == 4)
 
263
                        LPUT(R_ARM_REL32 | elfsym<<8);
 
264
                else
 
265
                        return -1;
 
266
                break;
 
267
        }
 
268
 
 
269
        return 0;
112
270
}
113
271
 
114
272
void
115
 
adddynsym(Sym *s)
116
 
{
117
 
        USED(s);
118
 
        diag("adddynsym: not implemented");
119
 
}
120
 
 
121
 
static void
122
273
elfsetupplt(void)
123
274
{
124
 
        // TODO
125
 
}
 
275
        Sym *plt, *got;
 
276
        
 
277
        plt = lookup(".plt", 0);
 
278
        got = lookup(".got.plt", 0);
 
279
        if(plt->size == 0) {
 
280
                // str lr, [sp, #-4]!
 
281
                adduint32(plt, 0xe52de004);
 
282
                // ldr lr, [pc, #4]
 
283
                adduint32(plt, 0xe59fe004);
 
284
                // add lr, pc, lr
 
285
                adduint32(plt, 0xe08fe00e);
 
286
                // ldr pc, [lr, #8]!
 
287
                adduint32(plt, 0xe5bef008);
 
288
                // .word &GLOBAL_OFFSET_TABLE[0] - .
 
289
                addpcrelplus(plt, got, 4);
 
290
 
 
291
                // the first .plt entry requires 3 .plt.got entries
 
292
                adduint32(got, 0);
 
293
                adduint32(got, 0);
 
294
                adduint32(got, 0);
 
295
        }
 
296
}
 
297
 
 
298
int
 
299
machoreloc1(Reloc *r, vlong sectoff)
 
300
{
 
301
        USED(r);
 
302
        USED(sectoff);
 
303
 
 
304
        return -1;
 
305
}
 
306
 
126
307
 
127
308
int
128
309
archreloc(Reloc *r, Sym *s, vlong *val)
129
310
{
130
 
        USED(r);
131
 
        USED(s);
132
 
        USED(val);
 
311
        switch(r->type) {
 
312
        case D_CONST:
 
313
                *val = r->add;
 
314
                return 0;
 
315
        case D_GOTOFF:
 
316
                *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
 
317
                return 0;
 
318
        // The following three arch specific relocations are only for generation of 
 
319
        // Linux/ARM ELF's PLT entry (3 assembler instruction)
 
320
        case D_PLT0: // add ip, pc, #0xXX00000
 
321
                if (symaddr(lookup(".got.plt", 0)) < symaddr(lookup(".plt", 0)))
 
322
                        diag(".got.plt should be placed after .plt section.");
 
323
                *val = 0xe28fc600U +
 
324
                        (0xff & ((uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add) >> 20));
 
325
                return 0;
 
326
        case D_PLT1: // add ip, ip, #0xYY000
 
327
                *val = 0xe28cca00U +
 
328
                        (0xff & ((uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add + 4) >> 12));
 
329
                return 0;
 
330
        case D_PLT2: // ldr pc, [ip, #0xZZZ]!
 
331
                *val = 0xe5bcf000U +
 
332
                        (0xfff & (uint32)(symaddr(r->sym) - (symaddr(lookup(".plt", 0)) + r->off) + r->add + 8));
 
333
                return 0;
 
334
        case D_CALL: // bl XXXXXX or b YYYYYY
 
335
                *val = braddoff((0xff000000U & (uint32)r->add), 
 
336
                                (0xffffff & (uint32)
 
337
                                   ((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
 
338
                return 0;
 
339
        }
133
340
        return -1;
134
341
}
135
342
 
 
343
static Reloc *
 
344
addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
 
345
{
 
346
        Reloc *r;
 
347
 
 
348
        r = addrel(plt);
 
349
        r->sym = got;
 
350
        r->off = plt->size;
 
351
        r->siz = 4;
 
352
        r->type = typ;
 
353
        r->add = sym->got - 8;
 
354
 
 
355
        plt->reachable = 1;
 
356
        plt->size += 4;
 
357
        symgrow(plt, plt->size);
 
358
 
 
359
        return r;
 
360
}
 
361
 
 
362
static void
 
363
addpltsym(Sym *s)
 
364
{
 
365
        Sym *plt, *got, *rel;
 
366
        
 
367
        if(s->plt >= 0)
 
368
                return;
 
369
 
 
370
        adddynsym(s);
 
371
        
 
372
        if(iself) {
 
373
                plt = lookup(".plt", 0);
 
374
                got = lookup(".got.plt", 0);
 
375
                rel = lookup(".rel.plt", 0);
 
376
                if(plt->size == 0)
 
377
                        elfsetupplt();
 
378
                
 
379
                // .got entry
 
380
                s->got = got->size;
 
381
                // In theory, all GOT should point to the first PLT entry,
 
382
                // Linux/ARM's dynamic linker will do that for us, but FreeBSD/ARM's
 
383
                // dynamic linker won't, so we'd better do it ourselves.
 
384
                addaddrplus(got, plt, 0);
 
385
 
 
386
                // .plt entry, this depends on the .got entry
 
387
                s->plt = plt->size;
 
388
                addpltreloc(plt, got, s, D_PLT0); // add lr, pc, #0xXX00000
 
389
                addpltreloc(plt, got, s, D_PLT1); // add lr, lr, #0xYY000
 
390
                addpltreloc(plt, got, s, D_PLT2); // ldr pc, [lr, #0xZZZ]!
 
391
 
 
392
                // rel
 
393
                addaddrplus(rel, got, s->got);
 
394
                adduint32(rel, ELF32_R_INFO(s->dynid, R_ARM_JUMP_SLOT));
 
395
        } else {
 
396
                diag("addpltsym: unsupported binary format");
 
397
        }
 
398
}
 
399
 
 
400
static void
 
401
addgotsyminternal(Sym *s)
 
402
{
 
403
        Sym *got;
 
404
        
 
405
        if(s->got >= 0)
 
406
                return;
 
407
 
 
408
        got = lookup(".got", 0);
 
409
        s->got = got->size;
 
410
 
 
411
        addaddrplus(got, s, 0);
 
412
 
 
413
        if(iself) {
 
414
                ;
 
415
        } else {
 
416
                diag("addgotsyminternal: unsupported binary format");
 
417
        }
 
418
}
 
419
 
 
420
static void
 
421
addgotsym(Sym *s)
 
422
{
 
423
        Sym *got, *rel;
 
424
        
 
425
        if(s->got >= 0)
 
426
                return;
 
427
        
 
428
        adddynsym(s);
 
429
        got = lookup(".got", 0);
 
430
        s->got = got->size;
 
431
        adduint32(got, 0);
 
432
        
 
433
        if(iself) {
 
434
                rel = lookup(".rel", 0);
 
435
                addaddrplus(rel, got, s->got);
 
436
                adduint32(rel, ELF32_R_INFO(s->dynid, R_ARM_GLOB_DAT));
 
437
        } else {
 
438
                diag("addgotsym: unsupported binary format");
 
439
        }
 
440
}
 
441
 
 
442
void
 
443
adddynsym(Sym *s)
 
444
{
 
445
        Sym *d;
 
446
        int t;
 
447
        char *name;
 
448
 
 
449
        if(s->dynid >= 0)
 
450
                return;
 
451
 
 
452
        if(iself) {
 
453
                s->dynid = nelfsym++;
 
454
 
 
455
                d = lookup(".dynsym", 0);
 
456
 
 
457
                /* name */
 
458
                name = s->extname;
 
459
                adduint32(d, addstring(lookup(".dynstr", 0), name));
 
460
 
 
461
                /* value */
 
462
                if(s->type == SDYNIMPORT)
 
463
                        adduint32(d, 0);
 
464
                else
 
465
                        addaddr(d, s);
 
466
 
 
467
                /* size */
 
468
                adduint32(d, 0);
 
469
 
 
470
                /* type */
 
471
                t = STB_GLOBAL << 4;
 
472
                if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
 
473
                        t |= STT_FUNC;
 
474
                else
 
475
                        t |= STT_OBJECT;
 
476
                adduint8(d, t);
 
477
                adduint8(d, 0);
 
478
 
 
479
                /* shndx */
 
480
                if(s->type == SDYNIMPORT)
 
481
                        adduint16(d, SHN_UNDEF);
 
482
                else {
 
483
                        switch(s->type) {
 
484
                        default:
 
485
                        case STEXT:
 
486
                                t = 11;
 
487
                                break;
 
488
                        case SRODATA:
 
489
                                t = 12;
 
490
                                break;
 
491
                        case SDATA:
 
492
                                t = 13;
 
493
                                break;
 
494
                        case SBSS:
 
495
                                t = 14;
 
496
                                break;
 
497
                        }
 
498
                        adduint16(d, t);
 
499
                }
 
500
        } else {
 
501
                diag("adddynsym: unsupported binary format");
 
502
        }
 
503
}
 
504
 
136
505
void
137
506
adddynlib(char *lib)
138
507
{
151
520
        }
152
521
}
153
522
 
154
 
void
155
 
doelf(void)
156
 
{
157
 
        Sym *s, *shstrtab, *dynstr;
158
 
 
159
 
        if(!iself)
160
 
                return;
161
 
 
162
 
        /* predefine strings we need for section headers */
163
 
        shstrtab = lookup(".shstrtab", 0);
164
 
        shstrtab->type = SELFROSECT;
165
 
        shstrtab->reachable = 1;
166
 
 
167
 
        elfstr[ElfStrEmpty] = addstring(shstrtab, "");
168
 
        elfstr[ElfStrText] = addstring(shstrtab, ".text");
169
 
        elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
170
 
        elfstr[ElfStrData] = addstring(shstrtab, ".data");
171
 
        elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
172
 
        elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
173
 
        if(HEADTYPE == Hnetbsd)
174
 
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
175
 
        addstring(shstrtab, ".rodata");
176
 
        addstring(shstrtab, ".gosymtab");
177
 
        addstring(shstrtab, ".gopclntab");
178
 
        if(!debug['s']) {       
179
 
                elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
180
 
                elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
181
 
        }
182
 
        elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
183
 
 
184
 
        if(!debug['d']) {       /* -d suppresses dynamic loader format */
185
 
                elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
186
 
                elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
187
 
                elfstr[ElfStrGot] = addstring(shstrtab, ".got");
188
 
                elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
189
 
                elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
190
 
                elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
191
 
                elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
192
 
                elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
193
 
                elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
194
 
                elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
195
 
 
196
 
                /* dynamic symbol table - first entry all zeros */
197
 
                s = lookup(".dynsym", 0);
198
 
                s->type = SELFROSECT;
199
 
                s->reachable = 1;
200
 
                s->value += ELF32SYMSIZE;
201
 
 
202
 
                /* dynamic string table */
203
 
                s = lookup(".dynstr", 0);
204
 
                s->type = SELFROSECT;
205
 
                s->reachable = 1;
206
 
                if(s->size == 0)
207
 
                        addstring(s, "");
208
 
                dynstr = s;
209
 
 
210
 
                /* relocation table */
211
 
                s = lookup(".rel", 0);
212
 
                s->reachable = 1;
213
 
                s->type = SELFROSECT;
214
 
 
215
 
                /* global offset table */
216
 
                s = lookup(".got", 0);
217
 
                s->reachable = 1;
218
 
                s->type = SELFSECT; // writable
219
 
                
220
 
                /* hash */
221
 
                s = lookup(".hash", 0);
222
 
                s->reachable = 1;
223
 
                s->type = SELFROSECT;
224
 
 
225
 
                /* got.plt */
226
 
                s = lookup(".got.plt", 0);
227
 
                s->reachable = 1;
228
 
                s->type = SELFSECT; // writable
229
 
                
230
 
                s = lookup(".plt", 0);
231
 
                s->reachable = 1;
232
 
                s->type = SELFROSECT;
233
 
 
234
 
                s = lookup(".rel.plt", 0);
235
 
                s->reachable = 1;
236
 
                s->type = SELFROSECT;
237
 
                
238
 
                elfsetupplt();
239
 
 
240
 
                /* define dynamic elf table */
241
 
                s = lookup(".dynamic", 0);
242
 
                s->reachable = 1;
243
 
                s->type = SELFSECT; // writable
244
 
 
245
 
                /*
246
 
                 * .dynamic table
247
 
                 */
248
 
                elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
249
 
                elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
250
 
                elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
251
 
                elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
252
 
                elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
253
 
                elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
254
 
                elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
255
 
                elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
256
 
                if(rpath)
257
 
                        elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
258
 
                elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
259
 
                elfwritedynent(s, DT_PLTREL, DT_REL);
260
 
                elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
261
 
                elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
262
 
                elfwritedynent(s, DT_DEBUG, 0);
263
 
                elfwritedynent(s, DT_NULL, 0);
264
 
        }
265
 
}
266
 
 
267
523
vlong
268
524
datoff(vlong addr)
269
525
{
276
532
}
277
533
 
278
534
void
279
 
shsym(Elf64_Shdr *sh, Sym *s)
280
 
{
281
 
        vlong addr;
282
 
        addr = symaddr(s);
283
 
        if(sh->flags&SHF_ALLOC)
284
 
                sh->addr = addr;
285
 
        sh->off = datoff(addr);
286
 
        sh->size = s->size;
287
 
}
288
 
 
289
 
void
290
 
phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
291
 
{
292
 
        ph->vaddr = sh->addr;
293
 
        ph->paddr = ph->vaddr;
294
 
        ph->off = sh->off;
295
 
        ph->filesz = sh->size;
296
 
        ph->memsz = sh->size;
297
 
        ph->align = sh->addralign;
298
 
}
299
 
 
300
 
void
301
535
asmb(void)
302
536
{
303
537
        int32 t;
304
 
        int a, dynsym;
305
 
        uint32 fo, symo, startva, resoff;
306
 
        ElfEhdr *eh;
307
 
        ElfPhdr *ph, *pph;
308
 
        ElfShdr *sh;
 
538
        uint32 symo;
309
539
        Section *sect;
310
 
        int o;
 
540
        Sym *sym;
 
541
        int i;
311
542
 
312
543
        if(debug['v'])
313
544
                Bprint(&bso, "%5.2f asmb\n", cputime());
314
545
        Bflush(&bso);
315
546
 
 
547
        if(iself)
 
548
                asmbelfsetup();
 
549
 
316
550
        sect = segtext.sect;
317
551
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
318
552
        codeblk(sect->vaddr, sect->len);
319
553
 
320
 
        /* output read-only data in text segment (rodata, gosymtab and pclntab) */
 
554
        /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
321
555
        for(sect = sect->next; sect != nil; sect = sect->next) {
322
556
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
323
557
                datblk(sect->vaddr, sect->len);
330
564
        cseek(segdata.fileoff);
331
565
        datblk(segdata.vaddr, segdata.filelen);
332
566
 
333
 
        if(iself) {
334
 
                /* index of elf text section; needed by asmelfsym, double-checked below */
335
 
                /* !debug['d'] causes extra sections before the .text section */
336
 
                elftextsh = 2;
337
 
                if(!debug['d']) {
338
 
                        elftextsh += 10;
339
 
                        if(elfverneed)
340
 
                                elftextsh += 2;
341
 
                }
342
 
                if(HEADTYPE == Hnetbsd)
343
 
                        elftextsh += 1;
344
 
        }
345
 
 
346
567
        /* output symbol table */
347
568
        symsize = 0;
348
569
        lcsize = 0;
365
586
                case Hplan9x32:
366
587
                        symo = HEADR+segtext.len+segdata.filelen;
367
588
                        break;
368
 
                case Hnetbsd:
369
 
                        symo = rnd(segdata.filelen, 4096);
370
 
                        break;
371
589
                ElfSym:
372
590
                        symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
373
591
                        symo = rnd(symo, INITRND);
374
592
                        break;
375
593
                }
376
594
                cseek(symo);
377
 
                if(iself) {
378
 
                        if(debug['v'])
379
 
                                Bprint(&bso, "%5.2f elfsym\n", cputime());
380
 
                        asmelfsym();
 
595
                switch(HEADTYPE) {
 
596
                default:
 
597
                        if(iself) {
 
598
                                if(debug['v'])
 
599
                                        Bprint(&bso, "%5.2f elfsym\n", cputime());
 
600
                                asmelfsym();
 
601
                                cflush();
 
602
                                cwrite(elfstrdat, elfstrsize);
 
603
        
 
604
                                if(debug['v'])
 
605
                                        Bprint(&bso, "%5.2f dwarf\n", cputime());
 
606
                                dwarfemitdebugsections();
 
607
                                
 
608
                                if(linkmode == LinkExternal)
 
609
                                        elfemitreloc();
 
610
                        }
 
611
                        break;
 
612
                case Hplan9x32:
 
613
                        asmplan9sym();
381
614
                        cflush();
382
 
                        cwrite(elfstrdat, elfstrsize);
383
 
 
384
 
                        // if(debug['v'])
385
 
                        //      Bprint(&bso, "%5.2f dwarf\n", cputime());
386
 
                        // dwarfemitdebugsections();
 
615
 
 
616
                        sym = lookup("pclntab", 0);
 
617
                        if(sym != nil) {
 
618
                                lcsize = sym->np;
 
619
                                for(i=0; i < lcsize; i++)
 
620
                                        cput(sym->p[i]);
 
621
 
 
622
                                cflush();
 
623
                        }
 
624
                        break;
387
625
                }
388
 
                cflush();
389
 
                
390
626
        }
391
627
 
392
628
        cursym = nil;
395
631
        Bflush(&bso);
396
632
        cseek(0L);
397
633
        switch(HEADTYPE) {
 
634
        default:
398
635
        case Hnoheader: /* no header */
399
636
                break;
400
637
        case Hrisc:     /* aif for risc os */
409
646
                         - 8) / 4);             /* BL - entry code */
410
647
 
411
648
                lputl(0xef000011);              /* SWI - exit code */
412
 
                lputl(textsize+HEADR);          /* text size */
 
649
                lputl(segtext.filelen+HEADR);           /* text size */
413
650
                lputl(segdata.filelen);                 /* data size */
414
651
                lputl(0);                       /* sym size */
415
652
 
429
666
                break;
430
667
        case Hplan9x32: /* plan 9 */
431
668
                lput(0x647);                    /* magic */
432
 
                lput(textsize);                 /* sizes */
 
669
                lput(segtext.filelen);                  /* sizes */
433
670
                lput(segdata.filelen);
434
671
                lput(segdata.len - segdata.filelen);
435
672
                lput(symsize);                  /* nsyms */
437
674
                lput(0L);
438
675
                lput(lcsize);
439
676
                break;
440
 
        case Hnetbsd:   /* boot for NetBSD */
441
 
                lput((143<<16)|0413);           /* magic */
442
 
                lputl(rnd(HEADR+textsize, 4096));
443
 
                lputl(rnd(segdata.filelen, 4096));
444
 
                lputl(segdata.len - segdata.filelen);
445
 
                lputl(symsize);                 /* nsyms */
446
 
                lputl(entryvalue());            /* va of entry */
447
 
                lputl(0L);
448
 
                lputl(0L);
449
 
                break;
450
677
        case Hixp1200: /* boot for IXP1200 */
451
678
                break;
452
679
        case Hipaq: /* boot for ipaq */
456
683
                lputl(0xe3300000);              /* nop */
457
684
                break;
458
685
        case Hlinux:
459
 
                /* elf arm */
460
 
                eh = getElfEhdr();
461
 
                fo = HEADR;
462
 
                startva = INITTEXT - fo;        /* va of byte 0 of file */
463
 
                resoff = ELFRESERVE;
464
 
                
465
 
                /* This null SHdr must appear before all others */
466
 
                newElfShdr(elfstr[ElfStrEmpty]);
467
 
 
468
 
                /* program header info */
469
 
                pph = newElfPhdr();
470
 
                pph->type = PT_PHDR;
471
 
                pph->flags = PF_R + PF_X;
472
 
                pph->off = eh->ehsize;
473
 
                pph->vaddr = INITTEXT - HEADR + pph->off;
474
 
                pph->paddr = INITTEXT - HEADR + pph->off;
475
 
                pph->align = INITRND;
476
 
 
477
 
                /*
478
 
                 * PHDR must be in a loaded segment. Adjust the text
479
 
                 * segment boundaries downwards to include it.
480
 
                 */
481
 
                o = segtext.vaddr - pph->vaddr;
482
 
                segtext.vaddr -= o;
483
 
                segtext.len += o;
484
 
                o = segtext.fileoff - pph->off;
485
 
                segtext.fileoff -= o;
486
 
                segtext.filelen += o;
487
 
 
488
 
                if(!debug['d']) {
489
 
                        /* interpreter for dynamic linking */
490
 
                        sh = newElfShdr(elfstr[ElfStrInterp]);
491
 
                        sh->type = SHT_PROGBITS;
492
 
                        sh->flags = SHF_ALLOC;
493
 
                        sh->addralign = 1;
494
 
                        if(interpreter == nil)
495
 
                                interpreter = linuxdynld;
496
 
                        resoff -= elfinterp(sh, startva, resoff, interpreter);
497
 
 
498
 
                        ph = newElfPhdr();
499
 
                        ph->type = PT_INTERP;
500
 
                        ph->flags = PF_R;
501
 
                        phsh(ph, sh);
502
 
                }
503
 
 
504
 
                if(HEADTYPE == Hnetbsd) {
505
 
                        sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
506
 
                        sh->type = SHT_NOTE;
507
 
                        sh->flags = SHF_ALLOC;
508
 
                        sh->addralign = 4;
509
 
                        resoff -= elfnetbsdsig(sh, startva, resoff);
510
 
 
511
 
                        ph = newElfPhdr();
512
 
                        ph->type = PT_NOTE;
513
 
                        ph->flags = PF_R;
514
 
                        phsh(ph, sh);
515
 
                }
516
 
 
517
 
                elfphload(&segtext);
518
 
                elfphload(&segdata);
519
 
 
520
 
                /* Dynamic linking sections */
521
 
                if(!debug['d']) {       /* -d suppresses dynamic loader format */
522
 
                        /* S headers for dynamic linking */
523
 
                        sh = newElfShdr(elfstr[ElfStrGot]);
524
 
                        sh->type = SHT_PROGBITS;
525
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
526
 
                        sh->entsize = 4;
527
 
                        sh->addralign = 4;
528
 
                        shsym(sh, lookup(".got", 0));
529
 
 
530
 
                        sh = newElfShdr(elfstr[ElfStrGotPlt]);
531
 
                        sh->type = SHT_PROGBITS;
532
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
533
 
                        sh->entsize = 4;
534
 
                        sh->addralign = 4;
535
 
                        shsym(sh, lookup(".got.plt", 0));
536
 
 
537
 
                        dynsym = eh->shnum;
538
 
                        sh = newElfShdr(elfstr[ElfStrDynsym]);
539
 
                        sh->type = SHT_DYNSYM;
540
 
                        sh->flags = SHF_ALLOC;
541
 
                        sh->entsize = ELF32SYMSIZE;
542
 
                        sh->addralign = 4;
543
 
                        sh->link = dynsym+1;    // dynstr
544
 
                        // sh->info = index of first non-local symbol (number of local symbols)
545
 
                        shsym(sh, lookup(".dynsym", 0));
546
 
 
547
 
                        sh = newElfShdr(elfstr[ElfStrDynstr]);
548
 
                        sh->type = SHT_STRTAB;
549
 
                        sh->flags = SHF_ALLOC;
550
 
                        sh->addralign = 1;
551
 
                        shsym(sh, lookup(".dynstr", 0));
552
 
 
553
 
                        sh = newElfShdr(elfstr[ElfStrHash]);
554
 
                        sh->type = SHT_HASH;
555
 
                        sh->flags = SHF_ALLOC;
556
 
                        sh->entsize = 4;
557
 
                        sh->addralign = 4;
558
 
                        sh->link = dynsym;
559
 
                        shsym(sh, lookup(".hash", 0));
560
 
 
561
 
                        sh = newElfShdr(elfstr[ElfStrRel]);
562
 
                        sh->type = SHT_REL;
563
 
                        sh->flags = SHF_ALLOC;
564
 
                        sh->entsize = ELF32RELSIZE;
565
 
                        sh->addralign = 4;
566
 
                        sh->link = dynsym;
567
 
                        shsym(sh, lookup(".rel", 0));
568
 
 
569
 
                        /* sh and PT_DYNAMIC for .dynamic section */
570
 
                        sh = newElfShdr(elfstr[ElfStrDynamic]);
571
 
                        sh->type = SHT_DYNAMIC;
572
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
573
 
                        sh->entsize = 8;
574
 
                        sh->addralign = 4;
575
 
                        sh->link = dynsym+1;    // dynstr
576
 
                        shsym(sh, lookup(".dynamic", 0));
577
 
 
578
 
                        ph = newElfPhdr();
579
 
                        ph->type = PT_DYNAMIC;
580
 
                        ph->flags = PF_R + PF_W;
581
 
                        phsh(ph, sh);
582
 
 
583
 
                        /*
584
 
                         * Thread-local storage segment (really just size).
585
 
                        if(tlsoffset != 0) {
586
 
                                ph = newElfPhdr();
587
 
                                ph->type = PT_TLS;
588
 
                                ph->flags = PF_R;
589
 
                                ph->memsz = -tlsoffset;
590
 
                                ph->align = 4;
591
 
                        }
592
 
                         */
593
 
                }
594
 
 
595
 
                ph = newElfPhdr();
596
 
                ph->type = PT_GNU_STACK;
597
 
                ph->flags = PF_W+PF_R;
598
 
                ph->align = 4;
599
 
 
600
 
                sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
601
 
                sh->type = SHT_STRTAB;
602
 
                sh->addralign = 1;
603
 
                shsym(sh, lookup(".shstrtab", 0));
604
 
 
605
 
                if(elftextsh != eh->shnum)
606
 
                        diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
607
 
                for(sect=segtext.sect; sect!=nil; sect=sect->next)
608
 
                        elfshbits(sect);
609
 
                for(sect=segdata.sect; sect!=nil; sect=sect->next)
610
 
                        elfshbits(sect);
611
 
 
612
 
                if(!debug['s']) {
613
 
                        sh = newElfShdr(elfstr[ElfStrSymtab]);
614
 
                        sh->type = SHT_SYMTAB;
615
 
                        sh->off = symo;
616
 
                        sh->size = symsize;
617
 
                        sh->addralign = 4;
618
 
                        sh->entsize = 16;
619
 
                        sh->link = eh->shnum;   // link to strtab
620
 
 
621
 
                        sh = newElfShdr(elfstr[ElfStrStrtab]);
622
 
                        sh->type = SHT_STRTAB;
623
 
                        sh->off = symo+symsize;
624
 
                        sh->size = elfstrsize;
625
 
                        sh->addralign = 1;
626
 
 
627
 
                        // dwarfaddelfheaders();
628
 
                }
629
 
 
630
 
                /* Main header */
631
 
                eh->ident[EI_MAG0] = '\177';
632
 
                eh->ident[EI_MAG1] = 'E';
633
 
                eh->ident[EI_MAG2] = 'L';
634
 
                eh->ident[EI_MAG3] = 'F';
635
 
                eh->ident[EI_CLASS] = ELFCLASS32;
636
 
                eh->ident[EI_DATA] = ELFDATA2LSB;
637
 
                eh->ident[EI_VERSION] = EV_CURRENT;
638
 
 
639
 
                eh->type = ET_EXEC;
640
 
                eh->machine = EM_ARM;
641
 
                eh->version = EV_CURRENT;
642
 
                eh->entry = entryvalue();
643
 
 
644
 
                if(pph != nil) {
645
 
                        pph->filesz = eh->phnum * eh->phentsize;
646
 
                        pph->memsz = pph->filesz;
647
 
                }
648
 
 
649
 
                cseek(0);
650
 
                a = 0;
651
 
                a += elfwritehdr();
652
 
                a += elfwritephdrs();
653
 
                a += elfwriteshdrs();
654
 
                a += elfwriteinterp(elfstr[ElfStrInterp]);
655
 
                if(HEADTYPE == Hnetbsd)
656
 
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
657
 
                if(a > ELFRESERVE)      
658
 
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
 
686
        case Hfreebsd:
 
687
        case Hnetbsd:
 
688
        case Hopenbsd:
 
689
                asmbelf(symo);
659
690
                break;
660
691
        }
661
692
        cflush();
662
693
        if(debug['c']){
663
 
                print("textsize=%d\n", textsize);
 
694
                print("textsize=%ulld\n", segtext.filelen);
664
695
                print("datsize=%ulld\n", segdata.filelen);
665
696
                print("bsssize=%ulld\n", segdata.len - segdata.filelen);
666
697
                print("symsize=%d\n", symsize);
667
698
                print("lcsize=%d\n", lcsize);
668
 
                print("total=%lld\n", textsize+segdata.len+symsize+lcsize);
 
699
                print("total=%lld\n", segtext.filelen+segdata.len+symsize+lcsize);
669
700
        }
670
701
}
671
702
 
812
843
 
813
844
        case 5:         /* bra s */
814
845
                v = -8;
 
846
                // TODO: Use addrel.
815
847
                if(p->cond != P)
816
848
                        v = (p->cond->pc - pc) - 8;
817
849
                o1 = opbra(p->as, p->scond);
875
907
                        rel = addrel(cursym);
876
908
                        rel->off = pc - cursym->value;
877
909
                        rel->siz = 4;
878
 
                        rel->type = D_ADDR;
879
910
                        rel->sym = p->to.sym;
880
911
                        rel->add = p->to.offset;
 
912
                        if(flag_shared) {
 
913
                                rel->type = D_PCREL;
 
914
                                rel->add += pc - p->pcrel->pc - 8;
 
915
                        } else
 
916
                                rel->type = D_ADDR;
881
917
                        o1 = 0;
882
918
                }
883
919
                break;
884
920
 
885
921
        case 12:        /* movw $lcon, reg */
886
922
                o1 = omvl(p, &p->from, p->to.reg);
 
923
                if(o->flag & LPCREL) {
 
924
                        o2 = oprrr(AADD, p->scond) | p->to.reg | REGPC << 16 | p->to.reg << 12;
 
925
                }
887
926
                break;
888
927
 
889
928
        case 13:        /* op $lcon, [R], R */
1128
1167
                r = p->reg;
1129
1168
                if(r == NREG) {
1130
1169
                        r = rt;
1131
 
                        if(p->as == AMOVF || p->as == AMOVD || p->as == ASQRTF || p->as == ASQRTD)
 
1170
                        if(p->as == AMOVF || p->as == AMOVD || p->as == ASQRTF || p->as == ASQRTD || p->as == AABSF || p->as == AABSD)
1132
1171
                                r = 0;
1133
1172
                }
1134
1173
                o1 |= rf | (r<<16) | (rt<<12);
1188
1227
                break;
1189
1228
 
1190
1229
        case 62:        /* case R -> movw       R<<2(PC),PC */
1191
 
                o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
1192
 
                o1 |= 2<<7;
 
1230
                if(o->flag & LPCREL) {
 
1231
                        o1 = oprrr(AADD, p->scond) | immrot(1) | p->from.reg << 16 | REGTMP << 12;
 
1232
                        o2 = olrr(REGTMP, REGPC, REGTMP, p->scond);
 
1233
                        o2 |= 2<<7;
 
1234
                        o3 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGPC << 12;
 
1235
                } else {
 
1236
                        o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
 
1237
                        o1 |= 2<<7;
 
1238
                }
1193
1239
                break;
1194
1240
 
1195
1241
        case 63:        /* bcase */
1196
 
                if(p->cond != P)
 
1242
                if(p->cond != P) {
1197
1243
                        o1 = p->cond->pc;
 
1244
                        if(flag_shared)
 
1245
                                o1 = o1 - p->pcrel->pc - 16;
 
1246
                }
1198
1247
                break;
1199
1248
 
1200
1249
        /* reloc ops */
1203
1252
                if(!o1)
1204
1253
                        break;
1205
1254
                o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
 
1255
                if(o->flag & LPCREL) {
 
1256
                        o3 = o2;
 
1257
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1258
                }
1206
1259
                break;
1207
1260
 
1208
1261
        case 65:        /* mov/movbu addr,R */
1212
1265
                o2 = olr(0, REGTMP, p->to.reg, p->scond);
1213
1266
                if(p->as == AMOVBU || p->as == AMOVB)
1214
1267
                        o2 |= 1<<22;
 
1268
                if(o->flag & LPCREL) {
 
1269
                        o3 = o2;
 
1270
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1271
                }
1215
1272
                break;
1216
1273
 
1217
1274
        case 68:        /* floating point store -> ADDR */
1219
1276
                if(!o1)
1220
1277
                        break;
1221
1278
                o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
 
1279
                if(o->flag & LPCREL) {
 
1280
                        o3 = o2;
 
1281
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1282
                }
1222
1283
                break;
1223
1284
 
1224
1285
        case 69:        /* floating point load <- ADDR */
1226
1287
                if(!o1)
1227
1288
                        break;
1228
1289
                o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
 
1290
                if(o->flag & LPCREL) {
 
1291
                        o3 = o2;
 
1292
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1293
                }
1229
1294
                break;
1230
1295
 
1231
1296
        /* ArmV4 ops: */
1422
1487
                        o2 ^= (1<<5)|(1<<6);
1423
1488
                else if(p->as == AMOVH)
1424
1489
                        o2 ^= (1<<6);
 
1490
                if(o->flag & LPCREL) {
 
1491
                        o3 = o2;
 
1492
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1493
                }
1425
1494
                break;
1426
1495
        case 94:        /* movh/movhu R,addr -> strh */
1427
1496
                o1 = omvl(p, &p->to, REGTMP);
1428
1497
                if(!o1)
1429
1498
                        break;
1430
1499
                o2 = oshr(p->from.reg, 0, REGTMP, p->scond);
 
1500
                if(o->flag & LPCREL) {
 
1501
                        o3 = o2;
 
1502
                        o2 = oprrr(AADD, p->scond) | REGTMP | REGPC << 16 | REGTMP << 12;
 
1503
                }
 
1504
                break;
 
1505
        case 95:        /* PLD off(reg) */
 
1506
                o1 = 0xf5d0f000;
 
1507
                o1 |= p->from.reg << 16;
 
1508
                if(p->from.offset < 0) {
 
1509
                        o1 &= ~(1 << 23);
 
1510
                        o1 |= (-p->from.offset) & 0xfff;
 
1511
                } else
 
1512
                        o1 |= p->from.offset & 0xfff;
 
1513
                break;
 
1514
        case 96:        /* UNDEF */
 
1515
                // This is supposed to be something that stops execution.
 
1516
                // It's not supposed to be reached, ever, but if it is, we'd
 
1517
                // like to be able to tell how we got there.  Assemble as
 
1518
                //      BL $0
 
1519
                // TODO: Use addrel.
 
1520
                v = (0 - pc) - 8;
 
1521
                o1 = opbra(ABL, C_SCOND_NONE);
 
1522
                o1 |= (v >> 2) & 0xffffff;
 
1523
                break;
 
1524
        case 97:        /* CLZ Rm, Rd */
 
1525
                o1 = oprrr(p->as, p->scond);
 
1526
                o1 |= p->to.reg << 12;
 
1527
                o1 |= p->from.reg;
 
1528
                break;
 
1529
        case 98:        /* MULW{T,B} Rs, Rm, Rd */
 
1530
                o1 = oprrr(p->as, p->scond);
 
1531
                o1 |= p->to.reg << 16;
 
1532
                o1 |= p->from.reg << 8;
 
1533
                o1 |= p->reg;
 
1534
                break;
 
1535
        case 99:        /* MULAW{T,B} Rs, Rm, Rn, Rd */
 
1536
                o1 = oprrr(p->as, p->scond);
 
1537
                o1 |= p->to.reg << 12;
 
1538
                o1 |= p->from.reg << 8;
 
1539
                o1 |= p->reg;
 
1540
                o1 |= p->to.offset << 16;
1431
1541
                break;
1432
1542
        }
1433
1543
        
1547
1657
        case ADIVF:     return o | (0xe<<24) | (0x8<<20) | (0xa<<8) | (0<<4);
1548
1658
        case ASQRTD:    return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xb<<8) | (0xc<<4);
1549
1659
        case ASQRTF:    return o | (0xe<<24) | (0xb<<20) | (1<<16) | (0xa<<8) | (0xc<<4);
 
1660
        case AABSD:     return o | (0xe<<24) | (0xb<<20) | (0<<16) | (0xb<<8) | (0xc<<4);
 
1661
        case AABSF:     return o | (0xe<<24) | (0xb<<20) | (0<<16) | (0xa<<8) | (0xc<<4);
1550
1662
        case ACMPD:     return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xb<<8) | (0xc<<4);
1551
1663
        case ACMPF:     return o | (0xe<<24) | (0xb<<20) | (4<<16) | (0xa<<8) | (0xc<<4);
1552
1664
 
1586
1698
                return o | (0xe<<24) | (0x1<<20) | (0xb<<8) | (1<<4);
1587
1699
        case ACMP+AEND: // cmp imm
1588
1700
                return o | (0x3<<24) | (0x5<<20);
 
1701
 
 
1702
        case ACLZ:
 
1703
                // CLZ doesn't support .S
 
1704
                return (o & (0xf<<28)) | (0x16f<<16) | (0xf1<<4);
 
1705
 
 
1706
        case AMULWT:
 
1707
                return (o & (0xf<<28)) | (0x12 << 20) | (0xe<<4);
 
1708
        case AMULWB:
 
1709
                return (o & (0xf<<28)) | (0x12 << 20) | (0xa<<4);
 
1710
        case AMULAWT:
 
1711
                return (o & (0xf<<28)) | (0x12 << 20) | (0xc<<4);
 
1712
        case AMULAWB:
 
1713
                return (o & (0xf<<28)) | (0x12 << 20) | (0x8<<4);
1589
1714
        }
1590
1715
        diag("bad rrr %d", a);
1591
1716
        prasm(curp);
1789
1914
int
1790
1915
chipzero(Ieee *e)
1791
1916
{
1792
 
        if(e->l != 0 || e->h != 0)
 
1917
        // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
 
1918
        if(goarm < 7 || e->l != 0 || e->h != 0)
1793
1919
                return -1;
1794
1920
        return 0;
1795
1921
}
1800
1926
        int n;
1801
1927
        ulong h;
1802
1928
 
 
1929
        // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
 
1930
        if(goarm < 7)
 
1931
                goto no;
 
1932
 
1803
1933
        if(e->l != 0 || (e->h&0xffff) != 0)
1804
1934
                goto no;
1805
1935
        h = e->h & 0x7fc00000;
1824
1954
no:
1825
1955
        return -1;
1826
1956
}
1827
 
 
1828
 
 
1829
 
void
1830
 
genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
1831
 
{
1832
 
        Auto *a;
1833
 
        Sym *s;
1834
 
        int h;
1835
 
 
1836
 
        s = lookup("etext", 0);
1837
 
        if(s->type == STEXT)
1838
 
                put(s, s->name, 'T', s->value, s->size, s->version, 0);
1839
 
 
1840
 
        for(h=0; h<NHASH; h++) {
1841
 
                for(s=hash[h]; s!=S; s=s->hash) {
1842
 
                        if(s->hide)
1843
 
                                continue;
1844
 
                        switch(s->type) {
1845
 
                        case SCONST:
1846
 
                        case SRODATA:
1847
 
                        case SDATA:
1848
 
                        case SELFROSECT:
1849
 
                        case STYPE:
1850
 
                        case SSTRING:
1851
 
                        case SGOSTRING:
1852
 
                        case SNOPTRDATA:
1853
 
                        case SSYMTAB:
1854
 
                        case SPCLNTAB:
1855
 
                                if(!s->reachable)
1856
 
                                        continue;
1857
 
                                put(s, s->name, 'D', s->value, s->size, s->version, s->gotype);
1858
 
                                continue;
1859
 
 
1860
 
                        case SBSS:
1861
 
                        case SNOPTRBSS:
1862
 
                                if(!s->reachable)
1863
 
                                        continue;
1864
 
                                if(s->np > 0)
1865
 
                                        diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
1866
 
                                put(s, s->name, 'B', s->value, s->size, s->version, s->gotype);
1867
 
                                continue;
1868
 
 
1869
 
                        case SFILE:
1870
 
                                put(nil, s->name, 'f', s->value, 0, s->version, 0);
1871
 
                                continue;
1872
 
                        }
1873
 
                }
1874
 
        }
1875
 
 
1876
 
        for(s = textp; s != nil; s = s->next) {
1877
 
                /* filenames first */
1878
 
                for(a=s->autom; a; a=a->link)
1879
 
                        if(a->type == D_FILE)
1880
 
                                put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
1881
 
                        else
1882
 
                        if(a->type == D_FILE1)
1883
 
                                put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
1884
 
 
1885
 
                put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
1886
 
 
1887
 
                /* frame, auto and param after */
1888
 
                put(nil, ".frame", 'm', s->text->to.offset+4, 0, 0, 0);
1889
 
 
1890
 
                for(a=s->autom; a; a=a->link)
1891
 
                        if(a->type == D_AUTO)
1892
 
                                put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
1893
 
                        else
1894
 
                        if(a->type == D_PARAM)
1895
 
                                put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
1896
 
        }
1897
 
        if(debug['v'] || debug['n'])
1898
 
                Bprint(&bso, "symsize = %ud\n", symsize);
1899
 
        Bflush(&bso);
1900
 
}
1901
 
 
1902
 
void
1903
 
setpersrc(Sym *s)
1904
 
{
1905
 
        USED(s);
1906
 
}