Revision 46152182

b/arm.ld
53 53
  .fini      : { *(.fini)    } =0x47ff041f
54 54
  .rodata    : { *(.rodata) *(.gnu.linkonce.r*) }
55 55
  .rodata1   : { *(.rodata1) }
56
  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
57
   __exidx_start = .;
58
  .ARM.exidx   : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
59
   __exidx_end = .;
56 60
  .reginfo : { *(.reginfo) }
57 61
  /* Adjust the address for the data segment.  We want to adjust up to
58 62
     the same address within the page on the next page up.  */
......
63 67
    *(.gnu.linkonce.d*)
64 68
    CONSTRUCTORS
65 69
  }
70
  .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
66 71
  .data1   : { *(.data1) }
72
  .preinit_array     :
73
  {
74
    PROVIDE_HIDDEN (__preinit_array_start = .);
75
    KEEP (*(.preinit_array))
76
    PROVIDE_HIDDEN (__preinit_array_end = .);
77
  }
78
  .init_array     :
79
  {
80
     PROVIDE_HIDDEN (__init_array_start = .);
81
     KEEP (*(SORT(.init_array.*)))
82
     KEEP (*(.init_array))
83
     PROVIDE_HIDDEN (__init_array_end = .);
84
  }
85
  .fini_array     :
86
  {
87
    PROVIDE_HIDDEN (__fini_array_start = .);
88
    KEEP (*(.fini_array))
89
    KEEP (*(SORT(.fini_array.*)))
90
    PROVIDE_HIDDEN (__fini_array_end = .);
91
  }
67 92
  .ctors         :
68 93
  {
69 94
    *(.ctors)
b/cpu-all.h
992 992
        return rval.i64;
993 993
#endif
994 994
}
995
#else
996
/* The host CPU doesn't have an easily accessible cycle counter.
997
   Just return a monotonically increasing vlue.  This will be totally wrong,
998
   but hopefully better than nothing.  */
999
static inline int64_t cpu_get_real_ticks (void)
1000
{
1001
    static int64_t ticks = 0;
1002
    return ticks++;
1003
}
995 1004
#endif
996 1005

  
997 1006
/* profiling */
b/disas.c
271 271
    for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
272 272
	fprintf(out, "0x%08lx:  ", pc);
273 273
#ifdef __arm__
274
        /* since data are included in the code, it is better to
274
        /* since data is included in the code, it is better to
275 275
           display code data too */
276
        if (is_host) {
277
            fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
278
        }
276
        fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
279 277
#endif
280 278
	count = print_insn(pc, &disasm_info);
281 279
	fprintf(out, "\n");
b/dyngen.c
1255 1255
{
1256 1256
    uint8_t *p;
1257 1257
    uint32_t insn;
1258
    int offset, min_offset, pc_offset, data_size;
1258
    int offset, min_offset, pc_offset, data_size, spare, max_pool;
1259 1259
    uint8_t data_allocated[1024];
1260 1260
    unsigned int data_index;
1261
    int type;
1261 1262
    
1262 1263
    memset(data_allocated, 0, sizeof(data_allocated));
1263 1264
    
1264 1265
    p = p_start;
1265 1266
    min_offset = p_end - p_start;
1267
    spare = 0x7fffffff;
1266 1268
    while (p < p_start + min_offset) {
1267 1269
        insn = get32((uint32_t *)p);
1270
        /* TODO: Armv5e ldrd.  */
1271
        /* TODO: VFP load.  */
1268 1272
        if ((insn & 0x0d5f0000) == 0x051f0000) {
1269 1273
            /* ldr reg, [pc, #im] */
1270 1274
            offset = insn & 0xfff;
1271 1275
            if (!(insn & 0x00800000))
1272
                        offset = -offset;
1276
                offset = -offset;
1277
            max_pool = 4096;
1278
            type = 0;
1279
        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1280
            /* FPA ldf.  */
1281
            offset = (insn & 0xff) << 2;
1282
            if (!(insn & 0x00800000))
1283
                offset = -offset;
1284
            max_pool = 1024;
1285
            type = 1;
1286
        } else if ((insn & 0x0fff0000) == 0x028f0000) {
1287
            /* Some gcc load a doubleword immediate with
1288
               add regN, pc, #imm
1289
               ldmia regN, {regN, regM}
1290
               Hope and pray the compiler never generates somethin like
1291
               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1292
            int r;
1293

  
1294
            r = (insn & 0xf00) >> 7;
1295
            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1296
            max_pool = 1024;
1297
            type = 2;
1298
        } else {
1299
            max_pool = 0;
1300
            type = -1;
1301
        }
1302
        if (type >= 0) {
1303
            /* PC-relative load needs fixing up.  */
1304
            if (spare > max_pool - offset)
1305
                spare = max_pool - offset;
1273 1306
            if ((offset & 3) !=0)
1274
                error("%s:%04x: ldr pc offset must be 32 bit aligned", 
1307
                error("%s:%04x: pc offset must be 32 bit aligned", 
1308
                      name, start_offset + p - p_start);
1309
            if (offset < 0)
1310
                error("%s:%04x: Embedded literal value",
1275 1311
                      name, start_offset + p - p_start);
1276 1312
            pc_offset = p - p_start + offset + 8;
1277 1313
            if (pc_offset <= (p - p_start) || 
1278 1314
                pc_offset >= (p_end - p_start))
1279
                error("%s:%04x: ldr pc offset must point inside the function code", 
1315
                error("%s:%04x: pc offset must point inside the function code", 
1280 1316
                      name, start_offset + p - p_start);
1281 1317
            if (pc_offset < min_offset)
1282 1318
                min_offset = pc_offset;
1283 1319
            if (outfile) {
1284
                /* ldr position */
1320
                /* The intruction position */
1285 1321
                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", 
1286 1322
                        p - p_start);
1287
                /* ldr data index */
1288
                data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
1289
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n", 
1323
                /* The position of the constant pool data.  */
1324
                data_index = ((p_end - p_start) - pc_offset) >> 2;
1325
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", 
1290 1326
                        data_index);
1327
                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1291 1328
                fprintf(outfile, "    arm_ldr_ptr++;\n");
1292
                if (data_index >= sizeof(data_allocated))
1293
                    error("%s: too many data", name);
1294
                if (!data_allocated[data_index]) {
1295
                    ELF_RELOC *rel;
1296
                    int i, addend, type;
1297
                    const char *sym_name, *p;
1298
                    char relname[1024];
1299

  
1300
                    data_allocated[data_index] = 1;
1301

  
1302
                    /* data value */
1303
                    addend = get32((uint32_t *)(p_start + pc_offset));
1304
                    relname[0] = '\0';
1305
                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1306
                        if (rel->r_offset == (pc_offset + start_offset)) {
1307
                            sym_name = get_rel_sym_name(rel);
1308
                            /* the compiler leave some unnecessary references to the code */
1309
                            get_reloc_expr(relname, sizeof(relname), sym_name);
1310
                            type = ELF32_R_TYPE(rel->r_info);
1311
                            if (type != R_ARM_ABS32)
1312
                                error("%s: unsupported data relocation", name);
1313
                            break;
1314
                        }
1315
                    }
1316
                    fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1317
                            data_index, addend);
1318
                    if (relname[0] != '\0')
1319
                        fprintf(outfile, " + %s", relname);
1320
                    fprintf(outfile, ";\n");
1321
                }
1322 1329
            }
1323 1330
        }
1324 1331
        p += 4;
1325 1332
    }
1333

  
1334
    /* Copy and relocate the constant pool data.  */
1326 1335
    data_size = (p_end - p_start) - min_offset;
1327 1336
    if (data_size > 0 && outfile) {
1328
        fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);
1337
        spare += min_offset;
1338
        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1339
        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1340
        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1341
                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
1342
                         spare, spare);
1343

  
1344
        data_index = 0;
1345
        for (pc_offset = min_offset;
1346
             pc_offset < p_end - p_start;
1347
             pc_offset += 4) {
1348

  
1349
            ELF_RELOC *rel;
1350
            int i, addend, type;
1351
            const char *sym_name;
1352
            char relname[1024];
1353

  
1354
            /* data value */
1355
            addend = get32((uint32_t *)(p_start + pc_offset));
1356
            relname[0] = '\0';
1357
            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1358
                if (rel->r_offset == (pc_offset + start_offset)) {
1359
                    sym_name = get_rel_sym_name(rel);
1360
                    /* the compiler leave some unnecessary references to the code */
1361
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1362
                    type = ELF32_R_TYPE(rel->r_info);
1363
                    if (type != R_ARM_ABS32)
1364
                        error("%s: unsupported data relocation", name);
1365
                    break;
1366
                }
1367
            }
1368
            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1369
                    data_index, addend);
1370
            if (relname[0] != '\0')
1371
                fprintf(outfile, " + %s", relname);
1372
            fprintf(outfile, ";\n");
1373

  
1374
            data_index++;
1375
        }
1329 1376
    }
1330 1377

  
1331
    /* the last instruction must be a mov pc, lr */
1332 1378
    if (p == p_start)
1333 1379
        goto arm_ret_error;
1334 1380
    p -= 4;
1335 1381
    insn = get32((uint32_t *)p);
1336
    if ((insn & 0xffff0000) != 0xe91b0000) {
1382
    /* The last instruction must be an ldm instruction.  There are several
1383
       forms generated by gcc:
1384
        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1385
        ldmia sp, {..., pc}
1386
        ldmea fp, {..., pc} */
1387
    if ((insn & 0xffff8000) == 0xe99d8000) {
1388
        if (outfile) {
1389
            fprintf(outfile,
1390
                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1391
                    p - p_start);
1392
        }
1393
        p += 4;
1394
    } else if ((insn & 0xffff8000) != 0xe89d8000
1395
        && (insn & 0xffff8000) != 0xe91b8000) {
1337 1396
    arm_ret_error:
1338 1397
        if (!outfile)
1339 1398
            printf("%s: invalid epilog\n", name);
1340 1399
    }
1341
    return p - p_start;	    
1400
    return p - p_start;
1342 1401
}
1343 1402
#endif
1344 1403

  
......
1537 1596
    }
1538 1597
#elif defined(HOST_ARM)
1539 1598
    {
1599
        uint32_t insn;
1600

  
1540 1601
        if ((p_end - p_start) <= 16)
1541 1602
            error("%s: function too small", name);
1542 1603
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
......
1545 1606
            error("%s: invalid prolog", name);
1546 1607
        p_start += 12;
1547 1608
        start_offset += 12;
1609
        insn = get32((uint32_t *)p_start);
1610
        if ((insn & 0xffffff00) == 0xe24dd000) {
1611
            /* Stack adjustment.  Assume op uses the frame pointer.  */
1612
            p_start -= 4;
1613
            start_offset -= 4;
1614
        }
1548 1615
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, 
1549 1616
                                      relocs, nb_relocs);
1550 1617
    }
......
2282 2349
                int type;
2283 2350
                int addend;
2284 2351
                int reloc_offset;
2285

  
2352
                uint32_t insn;
2353

  
2354
                insn = get32((uint32_t *)(p_start + 4));
2355
                /* If prologue ends in sub sp, sp, #const then assume
2356
                   op has a stack frame and needs the frame pointer.  */
2357
                if ((insn & 0xffffff00) == 0xe24dd000) {
2358
                    int i;
2359
                    uint32_t opcode;
2360
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2361
#if 0
2362
/* ??? Need to undo the extra stack adjustment at the end of the op.
2363
   For now just leave the stack misaligned and hope it doesn't break anything
2364
   too important.  */
2365
                    if ((insn & 4) != 0) {
2366
                        /* Preserve doubleword stack alignment.  */
2367
                        fprintf(outfile,
2368
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2369
                                insn + 4);
2370
                        opcode -= 4;
2371
                    }
2372
#endif
2373
                    insn = get32((uint32_t *)(p_start - 4));
2374
                    /* Calculate the size of the saved registers,
2375
                       excluding pc.  */
2376
                    for (i = 0; i < 15; i++) {
2377
                        if (insn & (1 << i))
2378
                            opcode += 4;
2379
                    }
2380
                    fprintf(outfile,
2381
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2382
                }
2286 2383
                arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
2287 2384
                                  relocs, nb_relocs);
2288 2385

  
......
2303 2400
                                reloc_offset, name, addend);
2304 2401
                        break;
2305 2402
                    case R_ARM_PC24:
2403
                    case R_ARM_JUMP24:
2404
                    case R_ARM_CALL:
2306 2405
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", 
2307 2406
                                reloc_offset, addend, name);
2308 2407
                        break;
......
2407 2506
        
2408 2507
    } else {
2409 2508
        /* generate big code generation switch */
2509

  
2510
#ifdef HOST_ARM
2511
        /* We need to know the size of all the ops so we can figure out when
2512
           to emit constant pools.  This must be consistent with opc.h.  */
2513
fprintf(outfile,
2514
"static const uint32_t arm_opc_size[] = {\n"
2515
"  0,\n" /* end */
2516
"  0,\n" /* nop */
2517
"  0,\n" /* nop1 */
2518
"  0,\n" /* nop2 */
2519
"  0,\n"); /* nop3 */
2520
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2521
            const char *name;
2522
            name = get_sym_name(sym);
2523
            if (strstart(name, OP_PREFIX, NULL)) {
2524
                fprintf(outfile, "  %d,\n", sym->st_size);
2525
            }
2526
	}
2527
fprintf(outfile,
2528
"};\n");
2529
#endif
2530

  
2410 2531
fprintf(outfile,
2411 2532
"int dyngen_code(uint8_t *gen_code_buf,\n"
2412 2533
"                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
......
2417 2538
"    const uint32_t *opparam_ptr;\n");
2418 2539

  
2419 2540
#ifdef HOST_ARM
2541
/* Arm is tricky because it uses constant pools for loading immediate values.
2542
   We assume (and require) each function is code followed by a constant pool.
2543
   All the ops are small so this should be ok.  For each op we figure
2544
   out how much "spare" range we have in the load instructions.  This allows
2545
   us to insert subsequent ops in between the op and the constant pool,
2546
   eliminating the neeed to jump around the pool.
2547

  
2548
   We currently generate:
2549
   
2550
   [ For this example we assume merging would move op1_pool out of range.
2551
     In practice we should be able to combine many ops before the offset
2552
     limits are reached. ]
2553
   op1_code;
2554
   op2_code;
2555
   goto op3;
2556
   op2_pool;
2557
   op1_pool;
2558
op3:
2559
   op3_code;
2560
   ret;
2561
   op3_pool;
2562

  
2563
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2564
 */
2420 2565
fprintf(outfile,
2421 2566
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2422 2567
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2423
"    uint32_t *arm_data_ptr = arm_data_table;\n");
2568
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2569
/* Initialise the parmissible pool offset to an arbitary large value.  */
2570
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2424 2571
#endif
2425 2572
#ifdef HOST_IA64
2426 2573
    {
......
2489 2636
	/* Generate prologue, if needed. */ 
2490 2637

  
2491 2638
fprintf(outfile,
2492
"    for(;;) {\n"
2493
"        switch(*opc_ptr++) {\n"
2494
);
2639
"    for(;;) {\n");
2640

  
2641
#ifdef HOST_ARM
2642
/* Generate constant pool if needed */
2643
fprintf(outfile,
2644
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2645
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2646
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2647
"                last_gen_code_ptr = gen_code_ptr;\n"
2648
"                arm_ldr_ptr = arm_ldr_table;\n"
2649
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2650
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2651
"            }\n");
2652
#endif
2653

  
2654
fprintf(outfile,
2655
"        switch(*opc_ptr++) {\n");
2495 2656

  
2496 2657
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2497 2658
            const char *name;
......
2525 2686
"            goto the_end;\n"
2526 2687
"        }\n");
2527 2688

  
2528
#ifdef HOST_ARM
2529
/* generate constant table if needed */
2530
fprintf(outfile,
2531
"        if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
2532
"            gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
2533
"            last_gen_code_ptr = gen_code_ptr;\n"
2534
"            arm_ldr_ptr = arm_ldr_table;\n"
2535
"            arm_data_ptr = arm_data_table;\n"
2536
"        }\n");         
2537
#endif
2538

  
2539 2689

  
2540 2690
fprintf(outfile,
2541 2691
"    }\n"
......
2553 2703

  
2554 2704
/* generate some code patching */ 
2555 2705
#ifdef HOST_ARM
2556
fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
2706
fprintf(outfile,
2707
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2708
"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2709
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2557 2710
#endif
2558 2711
    /* flush instruction cache */
2559 2712
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
b/dyngen.h
19 19
 */
20 20

  
21 21
int __op_param1, __op_param2, __op_param3;
22
#ifdef __sparc__
22
#if defined(__sparc__) || defined(__arm__)
23 23
  void __op_gen_label1(){}
24 24
  void __op_gen_label2(){}
25 25
  void __op_gen_label3(){}
......
145 145

  
146 146
#ifdef __arm__
147 147

  
148
#define MAX_OP_SIZE    (128 * 4) /* in bytes */
149
/* max size of the code that can be generated without calling arm_flush_ldr */
150
#define MAX_FRAG_SIZE  (1024 * 4) 
151
//#define MAX_FRAG_SIZE  (135 * 4) /* for testing */ 
148
#define ARM_LDR_TABLE_SIZE 1024
152 149

  
153 150
typedef struct LDREntry {
154 151
    uint8_t *ptr;
155 152
    uint32_t *data_ptr;
153
    unsigned type:2;
156 154
} LDREntry;
157 155

  
158 156
static LDREntry arm_ldr_table[1024];
159
static uint32_t arm_data_table[1024];
157
static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE];
160 158

  
161 159
extern char exec_loop;
162 160

  
......
175 173
    int offset, data_size, target;
176 174
    uint8_t *data_ptr;
177 175
    uint32_t insn;
176
    uint32_t mask;
178 177
 
179
    data_size = (uint8_t *)data_end - (uint8_t *)data_start;
178
    data_size = (data_end - data_start) << 2;
180 179

  
181 180
    if (gen_jmp) {
182 181
        /* generate branch to skip the data */
......
198 197
        offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + 
199 198
            (unsigned long)data_ptr - 
200 199
            (unsigned long)ptr - 8;
201
        insn = *ptr & ~(0xfff | 0x00800000);
202 200
        if (offset < 0) {
203
            offset = - offset;
204
        } else {
205
            insn |= 0x00800000;
206
        }
207
        if (offset > 0xfff) {
208
            fprintf(stderr, "Error ldr offset\n");
201
            fprintf(stderr, "Negative constant pool offset\n");
209 202
            abort();
210 203
        }
211
        insn |= offset;
204
        switch (le->type) {
205
          case 0: /* ldr */
206
            mask = ~0x00800fff;
207
            if (offset >= 4096) {
208
                fprintf(stderr, "Bad ldr offset\n");
209
                abort();
210
            }
211
            break;
212
          case 1: /* ldc */
213
            mask = ~0x008000ff;
214
            if (offset >= 1024 ) {
215
                fprintf(stderr, "Bad ldc offset\n");
216
                abort();
217
            }
218
            break;
219
          case 2: /* add */
220
            mask = ~0xfff;
221
            if (offset >= 1024 ) {
222
                fprintf(stderr, "Bad add offset\n");
223
                abort();
224
            }
225
            break;
226
          default:
227
            fprintf(stderr, "Bad pc relative fixup\n");
228
            abort();
229
          }
230
        insn = *ptr & mask;
231
        switch (le->type) {
232
          case 0: /* ldr */
233
            insn |= offset | 0x00800000;
234
            break;
235
          case 1: /* ldc */
236
            insn |= (offset >> 2) | 0x00800000;
237
            break;
238
          case 2: /* add */
239
            insn |= (offset >> 2) | 0xf00;
240
            break;
241
          }
212 242
        *ptr = insn;
213 243
    }
214 244
    return gen_code_ptr;
b/elf.h
502 502
#define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
503 503
#define R_ARM_GOT32		26	/* 32 bit GOT entry */
504 504
#define R_ARM_PLT32		27	/* 32 bit PLT address */
505
#define R_ARM_CALL              28
506
#define R_ARM_JUMP24            29
505 507
#define R_ARM_GNU_VTENTRY	100
506 508
#define R_ARM_GNU_VTINHERIT	101
507 509
#define R_ARM_THM_PC11		102	/* thumb unconditional branch */

Also available in: Unified diff