diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 998cd8d9c..c1651fcfe 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -3,3 +3,7 @@ * $State$ */ +#include + +extern quad emit_hi(struct expr_t* expr, bool is_signed); +extern quad emit_lo(struct expr_t* expr); diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 480c5faa3..3ecaf10cf 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -84,6 +84,9 @@ %token OP_LA %token OP_LI32 +%token OP_POWERPC_FIXUP +%token OP_HI OP_HA OP_LO + /* Other token types */ %type c diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 0f0bfdae7..724ba7312 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -102,6 +102,9 @@ 0, OP_LA, 0, "la", 0, OP_LA, 0, "li", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", +0, OP_HI, 0, "hi16", +0, OP_HA, 0, "ha16", +0, OP_LO, 0, "lo16", /* Branch processor instructions (page 20) */ @@ -270,7 +273,7 @@ 0, OP_RS_RA_SH_ME6_SH_C, 30<<26 | 1<<2, "rldicr", 0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 2<<2, "rldic", 0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", -0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", +0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", 0, OP_RS_RA_RB_ME6_C, 30<<26 | 9<<1, "rldcr", 0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", 0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index e1fb3fdf0..1ad180de4 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -19,9 +19,9 @@ operation | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } + | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } - | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } + | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } @@ -40,15 +40,15 @@ operation | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } + | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } - | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } | OP_RS_RA_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } | OP_RS_RA_RB_ME6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } | OP_RS_RA_SH_MB6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } @@ -66,7 +66,7 @@ c : /* nothing */ { $$ = 0; } | C { $$ = 1; } ; - + e16 : absexp { @@ -75,8 +75,11 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, false); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, true); } + | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } ; - + u8 : absexp { @@ -85,7 +88,7 @@ u8 $$ = $1; } ; - + u7 : absexp { @@ -94,7 +97,7 @@ u7 $$ = $1; } ; - + u6 : absexp { @@ -103,7 +106,7 @@ u6 $$ = $1; } ; - + u5 : absexp { @@ -112,7 +115,7 @@ u5 $$ = $1; } ; - + u4 : absexp { @@ -121,7 +124,7 @@ u4 $$ = $1; } ; - + u1 : absexp { @@ -130,7 +133,7 @@ u1 $$ = $1; } ; - + u2 : absexp { @@ -139,7 +142,7 @@ u2 $$ = $1; } ; - + ds : e16 { @@ -148,26 +151,26 @@ ds $$ = $1; } ; - + nb : absexp { if (($1 < 1) || ($1 > 32)) serror("register count must be in the range 1..32"); - + if ($1 == 32) $$ = 0; else - $$ = $1; + $$ = $1; } ; - + bdl : expr { int dist = $1.val - DOTVAL; fit(fitx(dist, 25)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -183,7 +186,7 @@ bda { int target = $1.val; fit(fitx(target, 16)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -193,7 +196,7 @@ bda $$ = target & 0xFFFD; } ; - + li32 : GPR ',' expr { @@ -215,7 +218,7 @@ lil { int dist = $1.val - DOTVAL; fit(fitx(dist, 26)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -223,13 +226,13 @@ lil $$ = dist & 0x03FFFFFD; } ; - + lia : expr { int target = $1.val; fit(fitx(target, 26)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -248,3 +251,14 @@ spr_num $$ = ($1 >> 5) | (($1 & 0x1f) << 5); } ; + +powerpcfixup + : expr + { + quad type = $1.typ & S_TYP; + quad val = $1.val; + if (type == S_ABS) + serror(".powerpcfixup is useless on absolute values"); + newrelo($1.typ, RELOPPC | FIXUPFLAGS); + } + ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 998cd8d9c..e3e23f272 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,5 +1,38 @@ -/* - * $Source$ - * $State$ - */ +quad emit_hi(struct expr_t* expr, bool is_signed) +{ + /* If this is a symbol reference, discard the symbol and keep only the + * offset part. */ + quad type = expr->typ & S_TYP; + quad val = expr->val; + uint16_t hi = val >> 16; + uint16_t lo = val & 0xffff; + + if (type != S_ABS) + newrelo(expr->typ, RELOPPC | FIXUPFLAGS); + + /* If the low half of this relocation is going to be a memory operation, + * then it'll be treated as a signed value. That means that values greater + * than 0x7fff will cause the high word to have 1 subtracted from it; so + * we apply an adjustment here. + */ + + if (is_signed && (lo > 0x7fff)) + hi++; + + return hi; +} + +quad emit_lo(struct expr_t* expr) +{ + quad type = expr->typ & S_TYP; + quad val = expr->val; + + /* If the assembler stored a symbol for relocation later, we need to + * abandon it (because the relocation was generated by emit_ha). */ + + if (type != S_ABS) + relonami = 0; + + return val & 0xffff; +} diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 6297f8889..1fc1f5b19 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -169,11 +169,15 @@ TOKENS /* Used only in instruction descriptions (to generate the correct syntax). */ GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". + GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". CONST = { INT val; } 4 val. /* Primitives */ LABEL = { ADDR adr; } 4 adr. + LABEL_OFFSET_HI = { ADDR adr; } 4 "hi16[" adr "]". + LABEL_OFFSET_HA = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_OFFSET_LO = { ADDR adr; } 4 "lo16[" adr "]". LOCAL = { INT off; } 4. /* Allows us to use regvar() to refer to registers */ @@ -282,7 +286,7 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HI+LABEL_OFFSET_HA:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. @@ -329,10 +333,9 @@ INSTRUCTIONS lhz GPR:wo, GPRINDIRECT:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). li32 GPR:wo, CONST:ro cost(8, 2). - li32 GPR:wo, LABEL:ro cost(8, 2). lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lwz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lwz GPR:wo, GPRINDIRECT+GPRINDIRECT_OFFSET_LO:ro cost(4, 3). nand GPR:wo, GPR:ro, GPR:ro. neg GPR:wo, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro. @@ -342,7 +345,7 @@ INSTRUCTIONS mtspr SPR:wo, GPR:ro cost(4, 2). or GPR:wo, GPR:ro, GPR:ro. orc GPR:wo, GPR:ro, GPR:ro. - ori GPR:wo, GPR:ro, CONST:ro. + ori GPR:wo, GPR:ro, CONST+LABEL_OFFSET_LO:ro. oris GPR:wo, GPR:ro, CONST:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. @@ -368,7 +371,7 @@ INSTRUCTIONS xori GPR:wo, GPR:ro, CONST:ro. xoris GPR:wo, GPR:ro, CONST:ro. - comment "!" LABEL:ro cost(0, 0). + comment "!" LABEL:ro cost(0, 0). @@ -405,7 +408,8 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - li32 %2, {LABEL, %1.adr} + addis %2, R0, {LABEL_OFFSET_HI, %1.adr} + ori %2, %2, {LABEL_OFFSET_LO, %1.adr} /* Sign extension */ @@ -1142,6 +1146,12 @@ PATTERNS yields {IND_RC_H, %1.reg, %1.off} pat loi $1==INT32 /* Load word indirect */ + with LABEL + uses REG + gen + addis %a, R0, {LABEL_OFFSET_HA, %1.adr} + lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} + yields %a with GPR yields {IND_RC_W, %1, 0} with SUM_RC diff --git a/man/powerpc_as.6 b/man/powerpc_as.6 new file mode 100644 index 000000000..8198d6bce --- /dev/null +++ b/man/powerpc_as.6 @@ -0,0 +1,33 @@ +.TH POWERPC_AS 1 +.ad +.SH NAME +powerpc_as \- assembler for PowerPC + +.SH SYNOPSIS +as [options] argument ... + +.SH DESCRIPTION +This assembler is made with the general framework +described in \fIuni_ass\fP(6). + +.SH SYNTAX +Most 32-bit integer and floating point instructions are supported, but not many +short form instructions. Instructions which take 16-bit operands can additionally +use the following special functions: + +.IP hi16[value], ha16[value] +Returns the high half of the value of the expression; if the value is not absolute, +also generates the appropriate fixup. Use of either of these \fImust\fR be followed, +in the next instruction, by the corresponding use of \fBlo16[]\fR. Use \fBhi16[]\fR +if the low half is going to interpret its payload as an unsigned value, and +\fBha16[]\fR if it will be interpreted as a signed value (so that the high half can +be adjusted to match). + +.IP lo16[] +Returns the low half of the value of the expression. No fixup is generated. Use of +\fBlo16[]\fR must come in the instruction immediately after a use of \fBhi16[]\fR or +\fBha16[]\fR. + +.SH "SEE ALSO" +uni_ass(6), +ack(1) diff --git a/util/led/archive.c b/util/led/archive.c index e36958d17..7e39e9fb7 100644 --- a/util/led/archive.c +++ b/util/led/archive.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include "arch.h" #include "out.h" #include "ranlib.h" diff --git a/util/led/const.h b/util/led/const.h index 40ad395b5..d2d27f51a 100644 --- a/util/led/const.h +++ b/util/led/const.h @@ -4,8 +4,6 @@ */ /* $Id$ */ -typedef int bool; - #define FALSE 0 #define TRUE 1 diff --git a/util/led/debug.h b/util/led/debug.h index 0e493185d..715409d25 100644 --- a/util/led/debug.h +++ b/util/led/debug.h @@ -17,3 +17,5 @@ extern int DEB; extern int Verbose; #define verbose(s, a1, a2, a3, a4) (Verbose && do_verbose(s, a1, a2, a3, a4)) + +extern void fatal(char* format, ...); diff --git a/util/led/error.c b/util/led/error.c index e7f4fc6ec..61dc7983e 100644 --- a/util/led/error.c +++ b/util/led/error.c @@ -6,9 +6,11 @@ static char rcsid[] = "$Id$"; #endif -#include -#include #include +#include +#include +#include +#include #include #include "const.h" @@ -73,7 +75,7 @@ do_verbose(char *format, ...) static void diag(char *tail, char *format, va_list ap) { - extern char *progname, *archname, *modulname; + extern char *progname, *archname, *modulname; fprintf(stderr, "%s: ", progname); if (archname && modulname) diff --git a/util/led/extract.c b/util/led/extract.c index 5878d527d..48a2f16c6 100644 --- a/util/led/extract.c +++ b/util/led/extract.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "debug.h" diff --git a/util/led/finish.c b/util/led/finish.c index 2eace760b..439d4b364 100644 --- a/util/led/finish.c +++ b/util/led/finish.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "defs.h" diff --git a/util/led/main.c b/util/led/main.c index 028bc3b3f..125f0c9a5 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -11,7 +11,9 @@ static char rcsid[] = "$Id$"; */ #include +#include #include +#include #include #include "const.h" #include "debug.h" @@ -168,7 +170,7 @@ first_pass(argv) case 'c': /* * Leave relocation information in the output, so that - * a next pass can see where relocation was done. The + * a next pass can see where relocation was done. The * resulting output however is no longer relocatable. */ flagword &= ~RFLAG; diff --git a/util/led/memory.c b/util/led/memory.c index 6349c826a..df4ee99d9 100644 --- a/util/led/memory.c +++ b/util/led/memory.c @@ -22,6 +22,9 @@ static char rcsid[] = "$Id$"; */ #include +#include +#include +#include #include #include "const.h" #include "assert.h" @@ -112,7 +115,7 @@ init_core() incore = FALSE; /* In core strategy failed. */ if (sbreak(AT_LEAST) == -1) fatal("no core at all"); - + base = BASE; for (mem = mems; mem < &mems[NMEMS]; mem++) { mem->mem_base = base; @@ -198,15 +201,15 @@ compact(piece, incr, flag) gain = (mem->mem_full + incr) >> SHIFT_COUNT; if (incr < gain) incr = gain; } - + /* * First, check that moving will result in enough space */ if (flag != FREEZE) { gain = mem->mem_left; for (mem = &mems[piece-1]; mem >= &mems[0]; mem--) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) @@ -224,8 +227,8 @@ compact(piece, incr, flag) } if (min == piece) for (mem = &mems[piece+1]; mem <= &mems[NMEMS - 1]; mem++) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) diff --git a/util/led/output.c b/util/led/output.c index 0ee622e3a..835627631 100644 --- a/util/led/output.c +++ b/util/led/output.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "memory.h" @@ -60,7 +64,7 @@ generate_section_names() extern struct outsect outsect[]; extern char *core_alloc(); - size = (long)outhead.oh_nsect * sizeof(struct outname); + size = (long)outhead.oh_nsect * sizeof(struct outname); name = (struct outname *)core_alloc(ALLOGLOB, size); if (name == (struct outname *)0) return; diff --git a/util/led/read.c b/util/led/read.c index 95ec7dd6b..3ea15925c 100644 --- a/util/led/read.c +++ b/util/led/read.c @@ -6,6 +6,11 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include + int infile; /* The current input file. */ rd_fatal() diff --git a/util/led/relocate.c b/util/led/relocate.c index c72965e75..7e2f9db10 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -9,6 +9,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include #include #include "out.h" #include "const.h" @@ -104,6 +105,24 @@ static uint32_t get_vc4_valu(char* addr) assert(0 && "unrecognised VC4 instruction"); } +static bool is_powerpc_memory_op(uint32_t opcode) +{ + /* Tests for any PowerPC memory indirection instruction where the payload + * is a *signed* 16-bit value. */ + switch ((opcode & 0xfc000000) >> 26) + { + case 34: /* lbz */ + case 40: /* lhz */ + case 32: /* lwz */ + case 38: /* stb */ + case 44: /* sth */ + case 36: /* stw */ + return true; + } + + return false; +} + /* PowerPC fixups are complex as we need to patch up to the next two * instructions in one of several different ways, depending on what the * instructions area. @@ -125,8 +144,23 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) /* addis / ori instruction pair */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = opcode1 & 0xffff; + uint16_t lo = opcode2 & 0xffff; - assert(0 && "unrecognised PowerPC instruction"); + /* Undo the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi--; + + return ((hi << 16) | lo); + } + + fatal("Don't know how to read from PowerPC fixup on instructions 0x%08x+0x%08x", + opcode1, opcode2); } /* @@ -263,14 +297,32 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) { + /* addis / ori instruction pair */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode2 & 0xffff0000) | lo, addr+4, type); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = value >> 16; + uint16_t lo = value & 0xffff; + + /* Apply the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi++; + + write4((opcode1 & 0xffff0000) | hi, addr+0, type); + write4((opcode2 & 0xffff0000) | lo, addr+4, type); + } + else - assert(0 && "unrecognised PowerPC instruction"); + fatal("Don't know how to write a PowerPC fixup to instructions 0x%08x+0x%08x", + opcode1, opcode2); } /* @@ -339,7 +391,7 @@ addrelo(relo, names, valu_out) extern int hash(); extern struct outname *searchname(); extern unsigned indexof(); - extern struct outhead outhead; + extern struct outhead outhead; name = searchname(local->on_mptr, hash(local->on_mptr)); if (name == (struct outname *)0) diff --git a/util/led/save.c b/util/led/save.c index 3804413d9..952649633 100644 --- a/util/led/save.c +++ b/util/led/save.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * If everything is kept in core, we must save some things for the second pass. */ -#include #include +#include +#include +#include #include #include "arch.h" #include "out.h" diff --git a/util/led/scan.c b/util/led/scan.c index a870f8e05..1740a14de 100644 --- a/util/led/scan.c +++ b/util/led/scan.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #ifdef SYMDBUG #include #include diff --git a/util/led/sym.c b/util/led/sym.c index 2ec47b6b7..53f0f3440 100644 --- a/util/led/sym.c +++ b/util/led/sym.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * Symbol table management. */ -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "memory.h" @@ -49,7 +51,7 @@ init_symboltable() * in the hash table is followed. If the names match, a pointer to the outname * in this element of the list is returned. When a match cannot be found, * NIL is returned. - */ + */ struct outname * searchname(string, hashval) char *string; @@ -74,7 +76,7 @@ searchname(string, hashval) debug("found %x, %x, %lx\n", name->on_type, name->on_desc, name->on_valu, 0); return name; - } + } symindex = sym->sy_next; } /* Not found. */ diff --git a/util/led/write.c b/util/led/write.c index d77ea98ef..b916949ae 100644 --- a/util/led/write.c +++ b/util/led/write.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include #include "out.h" #include "const.h" @@ -75,7 +77,7 @@ end_write() for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++) wrt_name(sectname(sectindex), 1); } - + wrt_emit(emit, sectindex, cnt) char *emit; int sectindex;