Merge pull request #45 from davidgiven/dtrg-fixups
Add hi16[], ha16[], lo16[] support to the PowerPC assembler
This commit is contained in:
		
						commit
						1a5c595a12
					
				
					 22 changed files with 245 additions and 61 deletions
				
			
		| 
						 | 
				
			
			@ -3,3 +3,7 @@
 | 
			
		|||
 * $State$
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
extern quad emit_hi(struct expr_t* expr, bool is_signed);
 | 
			
		||||
extern quad emit_lo(struct expr_t* expr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,6 +84,9 @@
 | 
			
		|||
%token <y_word> OP_LA
 | 
			
		||||
%token <y_word> OP_LI32
 | 
			
		||||
 | 
			
		||||
%token <y_word> OP_POWERPC_FIXUP
 | 
			
		||||
%token <y_word> OP_HI OP_HA OP_LO
 | 
			
		||||
 | 
			
		||||
/* Other token types */
 | 
			
		||||
 | 
			
		||||
%type <y_word> 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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
	}
 | 
			
		||||
	;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								man/powerpc_as.6
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								man/powerpc_as.6
									
										
									
									
									
										Normal 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "arch.h"
 | 
			
		||||
#include "out.h"
 | 
			
		||||
#include "ranlib.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,6 @@
 | 
			
		|||
 */
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
 | 
			
		||||
typedef int		bool;
 | 
			
		||||
 | 
			
		||||
#define FALSE		0
 | 
			
		||||
#define TRUE		1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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, ...);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,11 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "out.h"
 | 
			
		||||
#include "const.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#include "const.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,9 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,9 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,11 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
int	infile;	/* The current input file. */
 | 
			
		||||
 | 
			
		||||
rd_fatal()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,10 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
 * If everything is kept in core, we must save some things for the second pass.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "arch.h"
 | 
			
		||||
#include "out.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#ifdef SYMDBUG
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,10 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
 * Symbol table management.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#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. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,10 @@
 | 
			
		|||
static char rcsid[] = "$Id$";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue