Merge pull request #45 from davidgiven/dtrg-fixups

Add hi16[], ha16[], lo16[] support to the PowerPC assembler
This commit is contained in:
David Given 2017-01-18 20:18:04 +01:00 committed by GitHub
commit 1a5c595a12
22 changed files with 245 additions and 61 deletions

View file

@ -3,3 +3,7 @@
* $State$ * $State$
*/ */
#include <stdbool.h>
extern quad emit_hi(struct expr_t* expr, bool is_signed);
extern quad emit_lo(struct expr_t* expr);

View file

@ -84,6 +84,9 @@
%token <y_word> OP_LA %token <y_word> OP_LA
%token <y_word> OP_LI32 %token <y_word> OP_LI32
%token <y_word> OP_POWERPC_FIXUP
%token <y_word> OP_HI OP_HA OP_LO
/* Other token types */ /* Other token types */
%type <y_word> c %type <y_word> c

View file

@ -102,6 +102,9 @@
0, OP_LA, 0, "la", 0, OP_LA, 0, "la",
0, OP_LA, 0, "li", 0, OP_LA, 0, "li",
0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", 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) */ /* 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_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_MB6_SH_C, 30<<26 | 2<<2, "rldic",
0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", 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_ME6_C, 30<<26 | 9<<1, "rldcr",
0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", 0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm",
0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", 0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi",

View file

@ -19,9 +19,9 @@ operation
| OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | 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_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_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_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_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_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } | 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_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_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_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 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_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 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_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_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_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_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_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_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)); } | 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; } : /* nothing */ { $$ = 0; }
| C { $$ = 1; } | C { $$ = 1; }
; ;
e16 e16
: absexp : absexp
{ {
@ -75,8 +75,11 @@ e16
serror("16-bit value out of range"); serror("16-bit value out of range");
$$ = (uint16_t) $1; $$ = (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 u8
: absexp : absexp
{ {
@ -85,7 +88,7 @@ u8
$$ = $1; $$ = $1;
} }
; ;
u7 u7
: absexp : absexp
{ {
@ -94,7 +97,7 @@ u7
$$ = $1; $$ = $1;
} }
; ;
u6 u6
: absexp : absexp
{ {
@ -103,7 +106,7 @@ u6
$$ = $1; $$ = $1;
} }
; ;
u5 u5
: absexp : absexp
{ {
@ -112,7 +115,7 @@ u5
$$ = $1; $$ = $1;
} }
; ;
u4 u4
: absexp : absexp
{ {
@ -121,7 +124,7 @@ u4
$$ = $1; $$ = $1;
} }
; ;
u1 u1
: absexp : absexp
{ {
@ -130,7 +133,7 @@ u1
$$ = $1; $$ = $1;
} }
; ;
u2 u2
: absexp : absexp
{ {
@ -139,7 +142,7 @@ u2
$$ = $1; $$ = $1;
} }
; ;
ds ds
: e16 : e16
{ {
@ -148,26 +151,26 @@ ds
$$ = $1; $$ = $1;
} }
; ;
nb nb
: absexp : absexp
{ {
if (($1 < 1) || ($1 > 32)) if (($1 < 1) || ($1 > 32))
serror("register count must be in the range 1..32"); serror("register count must be in the range 1..32");
if ($1 == 32) if ($1 == 32)
$$ = 0; $$ = 0;
else else
$$ = $1; $$ = $1;
} }
; ;
bdl bdl
: expr : expr
{ {
int dist = $1.val - DOTVAL; int dist = $1.val - DOTVAL;
fit(fitx(dist, 25)); fit(fitx(dist, 25));
if (dist & 0x3) if (dist & 0x3)
serror("jump targets must be 4-aligned"); serror("jump targets must be 4-aligned");
@ -183,7 +186,7 @@ bda
{ {
int target = $1.val; int target = $1.val;
fit(fitx(target, 16)); fit(fitx(target, 16));
if (target & 0x3) if (target & 0x3)
serror("jump targets must be 4-aligned"); serror("jump targets must be 4-aligned");
@ -193,7 +196,7 @@ bda
$$ = target & 0xFFFD; $$ = target & 0xFFFD;
} }
; ;
li32 li32
: GPR ',' expr : GPR ',' expr
{ {
@ -215,7 +218,7 @@ lil
{ {
int dist = $1.val - DOTVAL; int dist = $1.val - DOTVAL;
fit(fitx(dist, 26)); fit(fitx(dist, 26));
if (dist & 0x3) if (dist & 0x3)
serror("jump targets must be 4-aligned"); serror("jump targets must be 4-aligned");
@ -223,13 +226,13 @@ lil
$$ = dist & 0x03FFFFFD; $$ = dist & 0x03FFFFFD;
} }
; ;
lia lia
: expr : expr
{ {
int target = $1.val; int target = $1.val;
fit(fitx(target, 26)); fit(fitx(target, 26));
if (target & 0x3) if (target & 0x3)
serror("jump targets must be 4-aligned"); serror("jump targets must be 4-aligned");
@ -248,3 +251,14 @@ spr_num
$$ = ($1 >> 5) | (($1 & 0x1f) << 5); $$ = ($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);
}
;

View file

@ -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;
}

View file

@ -169,11 +169,15 @@ TOKENS
/* Used only in instruction descriptions (to generate the correct syntax). */ /* Used only in instruction descriptions (to generate the correct syntax). */
GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")".
GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")".
CONST = { INT val; } 4 val. CONST = { INT val; } 4 val.
/* Primitives */ /* Primitives */
LABEL = { ADDR adr; } 4 adr. 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. LOCAL = { INT off; } 4.
/* Allows us to use regvar() to refer to registers */ /* Allows us to use regvar() to refer to registers */
@ -282,7 +286,7 @@ INSTRUCTIONS
add GPR:wo, GPR:ro, GPR:ro. add GPR:wo, GPR:ro, GPR:ro.
addX "add." GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro.
addi GPR:wo, GPR:ro, CONST: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. and GPR:wo, GPR:ro, GPR:ro.
andc GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro.
andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro.
@ -329,10 +333,9 @@ INSTRUCTIONS
lhz GPR:wo, GPRINDIRECT:ro cost(4, 3). lhz GPR:wo, GPRINDIRECT:ro cost(4, 3).
lhzx GPR:wo, GPR:ro, GPR: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, CONST:ro cost(8, 2).
li32 GPR:wo, LABEL:ro cost(8, 2).
lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3). lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3).
lwzx GPR:wo, GPR:ro, GPR: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. nand GPR:wo, GPR:ro, GPR:ro.
neg GPR:wo, GPR:ro. neg GPR:wo, GPR:ro.
nor GPR:wo, GPR:ro, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro.
@ -342,7 +345,7 @@ INSTRUCTIONS
mtspr SPR:wo, GPR:ro cost(4, 2). mtspr SPR:wo, GPR:ro cost(4, 2).
or GPR:wo, GPR:ro, GPR:ro. or GPR:wo, GPR:ro, GPR:ro.
orc 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. oris GPR:wo, GPR:ro, CONST:ro.
orX "or." GPR:wo:cc, GPR:ro, GPR:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro.
rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro.
@ -368,7 +371,7 @@ INSTRUCTIONS
xori GPR:wo, GPR:ro, CONST:ro. xori GPR:wo, GPR:ro, CONST:ro.
xoris 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 from LABEL to GPR
gen gen
COMMENT("move LABEL->GPR") 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 */ /* Sign extension */
@ -1142,6 +1146,12 @@ PATTERNS
yields {IND_RC_H, %1.reg, %1.off} yields {IND_RC_H, %1.reg, %1.off}
pat loi $1==INT32 /* Load word indirect */ 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 with GPR
yields {IND_RC_W, %1, 0} yields {IND_RC_W, %1, 0}
with SUM_RC with SUM_RC

33
man/powerpc_as.6 Normal file
View file

@ -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)

View file

@ -6,8 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "arch.h" #include "arch.h"
#include "out.h" #include "out.h"
#include "ranlib.h" #include "ranlib.h"

View file

@ -4,8 +4,6 @@
*/ */
/* $Id$ */ /* $Id$ */
typedef int bool;
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1

View file

@ -17,3 +17,5 @@ extern int DEB;
extern int Verbose; extern int Verbose;
#define verbose(s, a1, a2, a3, a4) (Verbose && do_verbose(s, a1, a2, a3, a4)) #define verbose(s, a1, a2, a3, a4) (Verbose && do_verbose(s, a1, a2, a3, a4))
extern void fatal(char* format, ...);

View file

@ -6,9 +6,11 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <out.h> #include <out.h>
#include "const.h" #include "const.h"
@ -73,7 +75,7 @@ do_verbose(char *format, ...)
static void static void
diag(char *tail, char *format, va_list ap) diag(char *tail, char *format, va_list ap)
{ {
extern char *progname, *archname, *modulname; extern char *progname, *archname, *modulname;
fprintf(stderr, "%s: ", progname); fprintf(stderr, "%s: ", progname);
if (archname && modulname) if (archname && modulname)

View file

@ -6,8 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "out.h" #include "out.h"
#include "const.h" #include "const.h"
#include "debug.h" #include "debug.h"

View file

@ -6,6 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <out.h> #include <out.h>
#include "const.h" #include "const.h"
#include "defs.h" #include "defs.h"

View file

@ -11,7 +11,9 @@ static char rcsid[] = "$Id$";
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <out.h> #include <out.h>
#include "const.h" #include "const.h"
#include "debug.h" #include "debug.h"
@ -168,7 +170,7 @@ first_pass(argv)
case 'c': case 'c':
/* /*
* Leave relocation information in the output, so that * 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. * resulting output however is no longer relocatable.
*/ */
flagword &= ~RFLAG; flagword &= ~RFLAG;

View file

@ -22,6 +22,9 @@ static char rcsid[] = "$Id$";
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <out.h> #include <out.h>
#include "const.h" #include "const.h"
#include "assert.h" #include "assert.h"
@ -112,7 +115,7 @@ init_core()
incore = FALSE; /* In core strategy failed. */ incore = FALSE; /* In core strategy failed. */
if (sbreak(AT_LEAST) == -1) if (sbreak(AT_LEAST) == -1)
fatal("no core at all"); fatal("no core at all");
base = BASE; base = BASE;
for (mem = mems; mem < &mems[NMEMS]; mem++) { for (mem = mems; mem < &mems[NMEMS]; mem++) {
mem->mem_base = base; mem->mem_base = base;
@ -198,15 +201,15 @@ compact(piece, incr, flag)
gain = (mem->mem_full + incr) >> SHIFT_COUNT; gain = (mem->mem_full + incr) >> SHIFT_COUNT;
if (incr < gain) incr = gain; if (incr < gain) incr = gain;
} }
/* /*
* First, check that moving will result in enough space * First, check that moving will result in enough space
*/ */
if (flag != FREEZE) { if (flag != FREEZE) {
gain = mem->mem_left; gain = mem->mem_left;
for (mem = &mems[piece-1]; mem >= &mems[0]; mem--) { 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 this does not give us enough, bad luck
*/ */
if (flag == FORCED) if (flag == FORCED)
@ -224,8 +227,8 @@ compact(piece, incr, flag)
} }
if (min == piece) if (min == piece)
for (mem = &mems[piece+1]; mem <= &mems[NMEMS - 1]; mem++) { 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 this does not give us enough, bad luck
*/ */
if (flag == FORCED) if (flag == FORCED)

View file

@ -6,6 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <out.h> #include <out.h>
#include "const.h" #include "const.h"
#include "memory.h" #include "memory.h"
@ -60,7 +64,7 @@ generate_section_names()
extern struct outsect outsect[]; extern struct outsect outsect[];
extern char *core_alloc(); 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); name = (struct outname *)core_alloc(ALLOGLOB, size);
if (name == (struct outname *)0) if (name == (struct outname *)0)
return; return;

View file

@ -6,6 +6,11 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
int infile; /* The current input file. */ int infile; /* The current input file. */
rd_fatal() rd_fatal()

View file

@ -9,6 +9,7 @@ static char rcsid[] = "$Id$";
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <assert.h> #include <assert.h>
#include "out.h" #include "out.h"
#include "const.h" #include "const.h"
@ -104,6 +105,24 @@ static uint32_t get_vc4_valu(char* addr)
assert(0 && "unrecognised VC4 instruction"); 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 /* 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 in one of several different ways, depending on what the
* instructions area. * instructions area.
@ -125,8 +144,23 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type)
/* addis / ori instruction pair */ /* addis / ori instruction pair */
return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); 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) && else if (((opcode1 & 0xfc1f0000) == 0x3c000000) &&
((opcode2 & 0xfc000000) == 0x60000000)) ((opcode2 & 0xfc000000) == 0x60000000))
{ {
/* addis / ori instruction pair */
uint16_t hi = value >> 16; uint16_t hi = value >> 16;
uint16_t lo = value & 0xffff; uint16_t lo = value & 0xffff;
write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode1 & 0xffff0000) | hi, addr+0, type);
write4((opcode2 & 0xffff0000) | lo, addr+4, 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 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 int hash();
extern struct outname *searchname(); extern struct outname *searchname();
extern unsigned indexof(); extern unsigned indexof();
extern struct outhead outhead; extern struct outhead outhead;
name = searchname(local->on_mptr, hash(local->on_mptr)); name = searchname(local->on_mptr, hash(local->on_mptr));
if (name == (struct outname *)0) if (name == (struct outname *)0)

View file

@ -10,8 +10,10 @@ static char rcsid[] = "$Id$";
* If everything is kept in core, we must save some things for the second pass. * If everything is kept in core, we must save some things for the second pass.
*/ */
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include "arch.h" #include "arch.h"
#include "out.h" #include "out.h"

View file

@ -6,8 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef SYMDBUG #ifdef SYMDBUG
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>

View file

@ -10,8 +10,10 @@ static char rcsid[] = "$Id$";
* Symbol table management. * Symbol table management.
*/ */
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "out.h" #include "out.h"
#include "const.h" #include "const.h"
#include "memory.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 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, * in this element of the list is returned. When a match cannot be found,
* NIL is returned. * NIL is returned.
*/ */
struct outname * struct outname *
searchname(string, hashval) searchname(string, hashval)
char *string; char *string;
@ -74,7 +76,7 @@ searchname(string, hashval)
debug("found %x, %x, %lx\n", debug("found %x, %x, %lx\n",
name->on_type, name->on_desc, name->on_valu, 0); name->on_type, name->on_desc, name->on_valu, 0);
return name; return name;
} }
symindex = sym->sy_next; symindex = sym->sy_next;
} }
/* Not found. */ /* Not found. */

View file

@ -6,8 +6,10 @@
static char rcsid[] = "$Id$"; static char rcsid[] = "$Id$";
#endif #endif
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include "out.h" #include "out.h"
#include "const.h" #include "const.h"
@ -75,7 +77,7 @@ end_write()
for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++) for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++)
wrt_name(sectname(sectindex), 1); wrt_name(sectname(sectindex), 1);
} }
wrt_emit(emit, sectindex, cnt) wrt_emit(emit, sectindex, cnt)
char *emit; char *emit;
int sectindex; int sectindex;