Add instructions like "lwarx". Extend manual.

Add more page numbers from PowerPC version 2.01.  Remove "xnop" not in
2.01, add "mtcr" from 2.01.  Add "lwarx" and the other instructions
from Book II.  I did not try all the newly added instructions, but
these seem to work: dcbt, dcbtst, icibi, isync, lwarx, stwcx., mftb,
mftbu

In man/powerpc_as.6 (not installed), add a summary of the registers
and addressing modes (like in i386_as.6), describe short forms, update
description of hi16/ha16, add CAVEATS about instructions that some
processors can't run.
This commit is contained in:
George Koehler 2018-03-07 13:37:31 -05:00
parent b1b737ed6c
commit b1badf1851
4 changed files with 230 additions and 56 deletions

View file

@ -47,11 +47,15 @@
%token <y_word> OP_FRT_FRB_C
%token <y_word> OP_FRT_RA_D
%token <y_word> OP_FRT_RA_RB
%token <y_word> OP_L
%token <y_word> OP_LEV
%token <y_word> OP_LIA
%token <y_word> OP_LIL
%token <y_word> OP_LI32
%token <y_word> OP_RA_RB
%token <y_word> OP_RA_RB_TH
%token <y_word> OP_RA_RS_C
%token <y_word> OP_RA_RS_RA_C
%token <y_word> OP_RA_RS_RB_C
%token <y_word> OP_RA_RS_RB_MB5_ME5_C
%token <y_word> OP_RA_RS_RB_MB6_C
@ -61,14 +65,14 @@
%token <y_word> OP_RA_RS_SH6_MB6_C
%token <y_word> OP_RA_RS_UI
%token <y_word> OP_RA_RS_UI_CC
%token <y_word> OP_RS
%token <y_word> OP_RS_FXM
%token <y_word> OP_RS_RA
%token <y_word> OP_RS_RA_D
%token <y_word> OP_RS_RA_DS
%token <y_word> OP_RS_RA_NB
%token <y_word> OP_RS_RA_RB
%token <y_word> OP_RS_RA_RB_C
%token <y_word> OP_RS_RA_RA_C
%token <y_word> OP_RS_RA_RB_CC
%token <y_word> OP_RS_RB
%token <y_word> OP_RS_SPR
%token <y_word> OP_RS_SR
@ -104,4 +108,5 @@
%type <y_word> c
%type <y_word> e16 negate16 u8 u7 u6 u5 u4 u2 u1
%type <y_word> opt_bh cr_opt nb ds bda bdl lia lil spr_num
%type <y_word> opt_bh cr_opt nb ds bda bdl lia lil
%type <y_word> spr_num tbr_num opt_tbr

View file

@ -103,6 +103,10 @@
0, OP_HA, 0, "ha16",
0, OP_LO, 0, "lo16",
/* The next page numbers are from PowerPC User Instruction Set
* Architecture, Book I, Version 2.01.
*/
/* Branch processor instructions (page 20) */
0, OP_LIL, 18<<26 | 0<<1 | 0<<0, "b",
@ -128,7 +132,7 @@
0, OP_BT_BA_BB, 19<<26 | 417<<1, "crorc",
0, OP_BF_BFA, 19<<26 | 0<<1, "mcrf",
/* extended mnemonics for bc, bcctr, bclr */
/* extended mnemonics for bc, bcctr, bclr (page 144) */
0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 0<<0, "bctr",
0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 1<<0, "bctrl",
0, OP_BDL, 16<<26 | 16<<21 | 0<<1 | 0<<0, "bdnz",
@ -186,7 +190,7 @@
0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 0<<0, "btlr",
0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 1<<0, "btlrl",
/* extended m with condition in BI */
/* extended m with condition in BI (page 146) */
0, OP_BICR_BDL, 16<<26 | 12<<21 | 2<<16 | 0<<1 | 0<<0, "beq",
0, OP_BICR_BDA, 16<<26 | 12<<21 | 2<<16 | 1<<1 | 0<<0, "beqa",
0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 528<<1 | 0<<0, "beqctr",
@ -284,7 +288,7 @@
0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 0<<0, "bunlr",
0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 1<<0, "bunlrl",
/* extended m for cr logic */
/* extended m for cr logic (page 147) */
0, OP_BT_BT_BT, 19<<26 | 289<<1, "crset",
0, OP_BT_BT_BT, 19<<26 | 193<<1, "crclr",
0, OP_BT_BA_BA, 19<<26 | 449<<1, "crmove",
@ -377,12 +381,12 @@
0, OP_RT_RA_C, 31<<26 | 0<<10 | 104<<1, "neg",
0, OP_RT_RA_C, 31<<26 | 1<<10 | 104<<1, "nego",
/* extended m for addition */
/* extended m for addition (pages 153, 154) */
0, OP_RT_RA_D, 14<<26, "la",
0, OP_RT_SI, 14<<26 | 0<<16, "li",
0, OP_RT_SI, 15<<26 | 0<<16, "lis",
/* extended m for subtraction */
/* extended m for subtraction (pages 147, 148) */
0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 40<<1, "sub",
0, OP_RT_RB_RA_C, 31<<26 | 1<<10 | 40<<1, "subo",
0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 8<<1, "subc",
@ -418,7 +422,7 @@
0, OP_BF_L_RA_UI, 10<<26, "cmpli",
0, OP_BF_L_RA_RB, 31<<26 | 32<<1, "cmpl",
/* extended m for comparison */
/* extended m for comparison (page 149) */
0, OP_BF_RA_SI, 11<<26 | 1<<21, "cmpdi",
0, OP_BF_RA_RB, 31<<26 | 1<<21 | 0<<1, "cmpd",
0, OP_BF_RA_UI, 10<<26 | 1<<21, "cmpldi",
@ -434,7 +438,7 @@
0, OP_TO_RA_RB, 31<<26 | 68<<1, "td",
0, OP_TO_RA_RB, 31<<26 | 4<<1, "tw",
/* extended m for traps */
/* extended m for traps (page 150) */
0, OP_TOX_RA_RB, 31<<26 | 4<<21 | 68<<1, "tdeq",
0, OP_TOX_RA_SI, 2<<26 | 4<<21, "tdeqi",
0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 68<<1, "tdge",
@ -518,11 +522,10 @@
0, OP_RA_RS_C, 31<<26 | 58<<1, "cntlzd",
0, OP_RA_RS_C, 31<<26 | 26<<1, "cntlzw",
/* extended m using logic */
0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr",
/* extended m using logic (pages 153, 154) */
0, OP_RA_RS_RA_C, 31<<26 | 444<<1, "mr",
0, OP, 24<<26, "nop",
0, OP_RS_RA_RA_C, 31<<26 | 124<<1, "not",
0, OP, 26<<26, "xnop",
0, OP_RA_RS_RA_C, 31<<26 | 124<<1, "not",
/* page 69 */
0, OP_RA_RS_SH6_MB6_C, 30<<26 | 0<<2, "rldicl",
@ -535,7 +538,7 @@
0, OP_RA_RS_SH6_MB6_C, 30<<26 | 3<<2, "rldimi",
0, OP_RA_RS_SH5_MB5_ME5_C, 20<<26, "rlwimi",
/* extended m for doubleword rotation */
/* extended m for doubleword rotation (page 151) */
0, OP_clrlsldi, 30<<26 | 2<<2, "clrlsldi",
0, OP_clrldi, 30<<26 | 0<<2, "clrldi",
0, OP_clrrdi, 30<<26 | 1<<2, "clrrdi",
@ -548,7 +551,7 @@
0, OP_sldi, 30<<26 | 1<<2, "sldi",
0, OP_srdi, 30<<26 | 0<<2, "srdi",
/* extended m for word rotation */
/* extended m for word rotation (page 152) */
0, OP_clrlslwi, 21<<26, "clrlslwi",
0, OP_clrlwi, 21<<26, "clrlwi",
0, OP_clrrwi, 21<<26, "clrrwi",
@ -573,21 +576,25 @@
0, OP_RA_RS_RB_C, 31<<26 | 792<<1, "sraw",
/* page 78 */
0, OP_RS_SPR, 31<<26 | 467<<1, "mtspr",
0, OP_RT_SPR, 31<<26 | 339<<1, "mfspr",
0, OP_RS_FXM, 31<<26 | 0<<21 | 144<<1, "mtcrf",
0, OP_RT, 31<<26 | 0<<21 | 19<<1, "mfcr",
0, OP_RS_SPR, 31<<26 | 467<<1, "mtspr",
0, OP_RT_SPR, 31<<26 | 339<<1, "mfspr",
0, OP_RS_FXM, 31<<26 | 0<<20 | 144<<1, "mtcrf",
0, OP_RT, 31<<26 | 0<<20 | 19<<1, "mfcr",
/* extended m for special purpose registers */
/* extended m for special purpose registers (page 153) */
0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 339<<1, "mfctr",
0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 339<<1, "mflr",
0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 339<<1, "mfxer",
0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 467<<1, "mtctr",
0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 467<<1, "mtlr",
0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 467<<1, "mtxer",
0, OP_RS, 31<<26 | 9<<16 | 0<<11 | 467<<1, "mtctr",
0, OP_RS, 31<<26 | 8<<16 | 0<<11 | 467<<1, "mtlr",
0, OP_RS, 31<<26 | 1<<16 | 0<<11 | 467<<1, "mtxer",
/* extended m for condition register (page 154) */
0, OP_RS, 31<<26 | 0<<20 | 255<<12 | 144<<1, "mtcr",
/* Floating point instructions (page 83) */
/* page 98 */
0, OP_FRT_RA_D, 48<<26, "lfs",
0, OP_FRT_RA_RB, 31<<26 | 535<<1, "lfsx",
0, OP_FRT_RA_D, 49<<26, "lfsu",
@ -606,6 +613,7 @@
0, OP_FRS_RA_RB, 31<<26 | 759<<1, "stfdux",
0, OP_FRS_RA_RB, 31<<26 | 983<<1, "stfiwx",
/* page 104 */
0, OP_FRT_FRB_C, 63<<26 | 72<<1, "fmr",
0, OP_FRT_FRB_C, 63<<26 | 40<<1, "fneg",
0, OP_FRT_FRB_C, 63<<26 | 264<<1, "fabs",
@ -629,6 +637,7 @@
0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 30<<1, "fnmsub",
0, OP_FRT_FRA_FRC_FRB_C, 59<<26 | 30<<1, "fnmsubs",
/* page 109 */
0, OP_FRT_FRB_C, 63<<26 | 12<<1, "frsp",
0, OP_FRT_FRB_C, 63<<26 | 814<<1, "fctid",
0, OP_FRT_FRB_C, 63<<26 | 815<<1, "fctidz",
@ -652,4 +661,31 @@
0, OP_FRT_FRB_C, 63<<26 | 26<<1, "frsqrte",
0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 23<<1, "fsel",
/* page 98 */
/* Storage control instructions (Book II, page 15) */
/* Book II, page 17 */
0, OP_RA_RB, 31<<26 | 982<<1, "icbi",
0, OP_RA_RB_TH /* page 35 */, 31<<26 | 278<<1, "dcbt",
0, OP_RA_RB, 31<<26 | 246<<1, "dcbtst",
0, OP_RA_RB, 31<<26 | 1014<<1, "dcbz",
0, OP_RA_RB, 31<<26 | 54<<1, "dcbst",
0, OP_RA_RB, 31<<26 | 86<<1, "dcbf",
0, OP, 19<<26 | 150<<1, "isync",
0, OP_RT_RA_RB, 31<<26 | 20<<1, "lwarx",
0, OP_RT_RA_RB, 31<<26 | 84<<1, "ldarx",
0, OP_RS_RA_RB_CC, 31<<26 | 150<<1 | 1<<0, "stwcx",
0, OP_RS_RA_RB_CC, 31<<26 | 150<<1 | 1<<0, "stdcx",
0, OP_L, 31<<26 | 598<<1, "sync",
0, OP, 31<<26 | 1<<21 | 598<<1, "lwsync",
0, OP, 31<<26 | 2<<21 | 598<<1, "ptesync",
0, OP, 31<<26 | 854<<1, "eieio",
/* Time base (Book II, page 30) */
0, OP_RT_TBR, 31<<26 | 371<<1, "mftb",
0, OP_RT, 31<<26 | 8<<11 | 13<<16 | 371<<1, "mftbu",
/* External control (Book II, page 33) */
0, OP_RT_RA_RB, 31<<26 | 310<<1, "eciwx",
0, OP_RS_RA_RB, 31<<26 | 438<<1, "ecowx",

View file

@ -42,7 +42,23 @@ operation
| OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($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)); }
| OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); }
| OP_L { emit4($1); }
| OP_L u2 { emit4($1 | ($2<<21)); }
| OP_LEV { emit4($1); }
| OP_LEV u7 { emit4($1 | ($2<<5)); }
| OP_RA_RB GPR ',' GPR
{ emit4($1 | ($2<<16) | ($4<<11)); }
| OP_RA_RB_TH GPR ',' GPR opt_bh
{ emit4($1 | $5 | ($2<<16) | ($4<<11)); }
/*
* For instructions with "mnemonic RS, RA, ..."
* OP_RA_RS_... swaps RS and RA to (RA<<21) || (RS<<16)
* OP_RS_RA_... keeps RS and RA as (RS<<21) || (RA<<16)
*/
| OP_RA_RS_C c GPR ',' GPR
{ emit4($1 | $2 | ($5<<21) | ($3<<16)); }
| OP_RA_RS_RA_C c GPR ',' GPR
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); }
| OP_RA_RS_RB_C c GPR ',' GPR ',' GPR
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
| OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5
@ -75,20 +91,19 @@ operation
| OP_RT_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); }
| OP_RT_SI GPR ',' e16 { emit_hl($1 | ($2<<21) | $4); }
| OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); }
| OP_RT_TBR GPR opt_tbr { emit4($1 | ($2<<21) | ($3<<11)); }
| OP_RS GPR { emit4($1 | ($2<<21)); }
| OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); }
| OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_NB GPR ',' GPR ',' nb { 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_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); }
| OP_RS_RA_RB_CC C GPR ',' GPR ',' GPR { emit4($1 | ($3<<21) | ($5<<16) | ($7<<11)); }
| OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); }
| OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_TO_RA_SI u5 ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); }
| OP_TOX_RA_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); }
| OP_TOX_RA_SI GPR ',' e16 { emit_hl($1 | ($2<<16) | $4); }
| OP_LEV { emit4($1); }
| OP_LEV u7 { emit4($1 | ($2<<5)); }
| OP_LIA lia { emit4($1 | $2); }
| OP_LIL lil { emit4($1 | $2); }
| OP_LI32 li32 /* emitted in subrule */
@ -298,7 +313,7 @@ u2
}
;
/* Optional comma, branch hint. */
/* Optional comma, branch hint (or touch hint). */
opt_bh
: /* nothing */ { $$ = 0; }
| ',' u2 { $$ = ($2<<11); }
@ -409,13 +424,28 @@ lia
}
;
/*
* Instructions "mfspr", "mtspr", and "mftb" encode the 10-bit special
* purpose register (spr) or time base register (tbr) by swapping the
* low 5 bits with the high 5 bits. The value from an SPR token has
* already been swapped.
*/
spr_num
: SPR { $$ = $1; }
| absexp
: SPR { $$ = $1; }
| tbr_num { $$ = $1; }
;
opt_tbr
: /* nothing */ { $$ = 8 | (12<<5); }
| ',' tbr_num { $$ = $2; }
;
tbr_num
: absexp
{
if (($1 < 0) || ($1 > 0x3ff))
serror("spr number out of range");
/* mfspr, mtspr swap the low and high 5 bits */
serror("10-bit unsigned value out of range");
$$ = ($1 >> 5) | (($1 & 0x1f) << 5);
}
;

View file

@ -1,33 +1,136 @@
.TH POWERPC_AS 1
.TH POWERPC_AS 1 2018-03-07
.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).
.PP
It can assemble the instructions from Book I and Book II of PowerPC
version 2.01.
This includes the branch, integer, and floating point instructions
from Book I; and the cache, synchronization, and time base
instructions from Book II.
.PP
There is no support for other instructions, such as supervisor-mode
instructions or vector instructions.
There is some support for 64-bit integer instructions, but the
assembler only has 32-bit symbols.
.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.
.SS general purpose registers
There are 32 GPRs from \fBr0\fP to \fBr31\fP.
In this assembler, \fBsp\fP is an alias for \fBr1\fP, and \fBfp\fP is
an alias for \fBr2\fP, because \fIack\fP uses r1 as the stack pointer
and r2 as the frame pointer.
Other compilers don't use r2 as the frame pointer.
.PP
GPR syntax requires a register name, not a number.
For example, \(oqaddi\ r5,\ r4,\ 1\(cq works, but
\(oqaddi\ 5,\ 4,\ 1\(cq is a syntax error.
.PP
Certain instructions ignore the contents of \fBr0\fP and use zero.
This happens when using r0 as the second operand of \fIaddi\fP or
\fIaddis\fP, or when addressing \(oqexpr(r0)\(cq or
\(oqr0,\ gpr\(cq.
The syntax is still the name r0, not the number 0.
.SS floating point registers
There are 32 FPRs from \fBf0\fP to \fBf31\fP.
Each FPR has 64 bits and can hold a single-precision or
double-precision number.
FPR syntax requires a register name, not a number.
.SS special purpose registers
The three named SPRs are \fBctr\fP (count register), \fBlr\fP (link
register), and \fBxer\fP (exception register).
\(oqmfspr\(cq and \(oqmtspr\(cq allow these names or a number.
.SS condition register
There is a 32-bit condition register, where bit 0 is most significant,
and bit 31 is least significant.
This gets split into 8 registers of 4 bits each, from \fBcr0\fP (with
bits 0 to 3) to \fBcr7\fP (with bits 28 to 31).
Some instructions use the names cr0 to cr7, others use a bit numbered
0 to 31, and others use all 32 bits.
.SS addressing modes
\(oqexpr(gpr)\(cq addresses \fIexpr\fP + the contents of \fIgpr\fP,
except that \(oqexpr(r0)\(cq addresses \fIexpr\fP\ +\ 0.
A few instructions, like \(oqstwu\(cq, also update \fIgpr\fP by
setting it to the address.
.PP
\(oqgprA,\ gprB\(cq in certain instructions addresses the contents of
\fIgprA\fP + the contents of \fIgprB\fP, except that \(oqr0,\ gprB\(cq
addresses 0\ +\ the contents of \fIgprB\fP.
.SS 16-bit operands
Some instructions have a 16-bit operand.
This can be a bare \fIexpr\fP (which must fit signed or unsigned
16 bits), or it can be one of these special functions:
.IP "hi16[expr], ha16[expr]"
Returns the high half of the 32-bit value of the expression.
If the low half is negative (from 0x8000 to 0xffff),
then \fBha16[]\fP adjusts the high half by adding 1.
Use \fBhi16[]\fP if the instruction with \fBlo16[]\fP is going to
interpret its operand as an unsigned value, or \fBha16[]\fP if it will
interpret it as signed.
.IP
If \fIexpr\fP is not absolute, then the assembler must generate a
fixup for the linker.
The fixup only works if the instruction is
\(oqaddis gpr, r0, hx16[expr]\(cq or \(oqlis gpr, hx16[expr]\(cq.
.IP lo16[expr]
Returns the low half of the 32-bit value of the expression.
.SS short forms
Some instructions have short forms using extended mnemonics (or
simplified mnemonics) like \fIli\fP, \fIsrwi\fP, and many others.
.IP "li r6, 789"
is short for: addi r6, r0, 789
.IP "srwi r3, r4, 2"
is short for: rlwinm r3, r4, 30, 2, 31
.PP
This assembler doesn't support extended mnemonics with branch
prediction, such as \fIblt+\fP or \fIbne-\fP.
It always parses \(oq+\(cq and \(oq-\(cq as operators,
never as part of a mnemonic.
.SH EXAMPLES
There are two ways to load r3 with _symbol\ =\ 0x1234abcd.
One way is
.PP
.nf
lis r3, hi16[_symbol]
ori r3, r3, lo16[_symbol] ! r3 = 0x12340000 | 0x0000abcd
.fi
.PP
The other way is
.PP
.nf
lis r3, ha16[_symbol]
addi r3, r3, lo16[_symbol] ! r3 = 0x12350000 + 0xffffabcd
.fi
.PP
The next code adds 1 to a global variable.
.PP
.nf
lis r3, ha16[_var]
lwz r4, lo16[_var](r3)
addi r4, r4, 1
stw r4, lo16[_var](r3)
.fi
.SH "SEE ALSO"
uni_ass(6),
ack(1)
.PP
Freescale Semiconductor, \fIProgramming Environments Manual for 32-Bit
Implementations of the PowerPC Architecture\fP, Rev. 3, September 2005.
.PP
IBM, \fIPowerPC User Instruction Set Architecture, Book I\fP, Version
2.01, September 2003.
.PP
IBM, \fIPowerPC Virtual Environment Architecture, Book II\fP, Version
2.01, December 2003.
.SH CAVEATS
Beware that not every processor can run every instruction.
The 32-bit processors can't run 64-bit instructions like \fIlwa\fP,
\fIstd\fP, and \fIfctid\fP.
The PowerPC 601 can't run \fIstfiwx\fP, nor \fIfres\fP, \fIfrsqrte\fP,
\fIfsel\fP.
Many models, like the PowerPC G4, can't run \fIfsqrt\fP nor
\fIfsqrts\fP.