Files
Sylpheed/tools/ppc-manual/branch/bcx.md
MechaCat02 10dc260f0c chore(tools): adopt the PPC manual and a canary launcher that works anywhere
CONSOLIDATION.md Phase 6. Both lived untracked in the project root -- on one
disk, backed up by nothing.

  tools/ppc-manual/   393 files, 3.7 MB. 455 instructions, 350 family pages,
                      598 mnemonics resolvable through index.json, plus the
                      generator that produced them.
  tools/run-canary.sh the oracle launcher.

🔴 THE LAUNCHER WAS BROKEN IN TWO WAYS AND IS REWRITTEN, not copied:

  * it pointed at `xenia-rs/sylpheed.iso`, a SYMLINK. Wine cannot resolve one
    and says "path invalid", which reads as a corrupt image rather than a path
    problem -- it has cost a session before. It now points at the real file and
    warns if handed a symlink.
  * it hardcoded one machine's absolute paths, and named `xenia-rs`, which this
    consolidation retires. Now derived from the script's own location, with
    SYLPH_CANARY_BIN / SYLPH_ISO overrides and a check that each exists.

The standing constraints are in its header where someone will read them: one
emulator at a time, Canary runs MUTED, and never judge a crash or a hang from
a Bash-launched run -- a SIGKILL that looked like the binary was the editor's
process supervisor.

⚠️ The manual's GENERATOR reads the xenia-rs source tree, which is going away.
Its decoder now lives here as crates/sylpheed-ppc, so the generator must be
repointed before it is run again. Recorded in the README rather than left for
someone to discover; the manual's content is checked in and regenerates from
nothing implicitly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 21:18:00 +02:00

9.1 KiB
Raw Blame History

bcx — Branch Conditional

Category: Branch & System · Form: B · Opcode: 0x40000000 · sync

Assembler Mnemonics

Mnemonic XML entry Flags Description
bc bcx Branch Conditional
bcl bcx LK=1 Branch Conditional

Syntax

bc[LK][AA] [BO], [BI], [ADDR]

Encoding

bcx — form B

  • Opcode word: 0x40000000
  • Primary opcode (bits 05): 16
  • Extended opcode:
  • Synchronising: yes
Bits Field Meaning
05 OPCD primary opcode
610 BO branch options
1115 BI CR bit to test
1629 BD signed 14-bit word-offset target
30 AA absolute-address flag
31 LK link flag

Operands

Field Role Description
LK bcx: read Link bit. When 1, LR ← address-of-next-instruction before the branch is taken.
AA bcx: read Absolute-address bit. When 1, the branch target is the sign-extended displacement itself; when 0, it is added to the current instruction address.
BO bcx: read 5-bit branch options — selects CTR decrement, CTR test polarity, and CR bit test polarity. See forms/XL.md.
BI bcx: read CR bit index (031) selected by BO's condition test.
ADDR bcx: read Encoded branch target displacement (24-bit for I-form, 14-bit for B-form, word-shifted).
CR bcx: read (conditional) Condition-register update. When Rc=1, CR field 0 (or CR6 for vector compares, CR1 for FPU) is updated from the result.
CTR bcx: read (conditional); bcx: write (conditional) Count register. Decremented and optionally tested by conditional branches when BO[2]=0.
LR bcx: write (conditional) Link register. Written by bl/bla/bcl/bclrl/bcctrl; read by bclr/bclrl.

Register Effects

bcx

  • Reads (always): LK, AA, BO, BI, ADDR
  • Reads (conditional): CR, CTR
  • Writes (always): none
  • Writes (conditional): CTR, LR

Status-Register Effects

No condition-register or status-register effects.

Operation (pseudocode)

if ¬BO[2] then CTR <- CTR  1
ctr_ok  <- BO[2] | ((CTR ≠ 0) XOR BO[3])
cond_ok <- BO[0] | (CR[BI] ≡ BO[1])
if ctr_ok & cond_ok then NIA <- CIA + EXTS(BD || 0b00)  (AA=0)
                                       EXTS(BD || 0b00)  (AA=1)
if LK then LR <- CIA + 4

C Translation Example

/* C translation: the xenia-rs interpreter arm below in           */
/* Implementation References is the authoritative semantic        */
/* snapshot. Translate it line-by-line:                            */
/*   - ctx.gpr[N]  -> r[N]       (or f[]/v[] for FPRs/VRs)        */
/*   - mem.read_u*/write_u* -> mem_read_u*_be / mem_write_u*_be   */
/*   - ctx.update_cr_signed(fld, v) -> update_cr_signed(fld, v)   */
/*   - ctx.xer_ca / xer_ov / xer_so -> xer.CA / xer.OV / xer.SO   */
/* The Register Effects and Status-Register Effects tables above  */
/* enumerate every side effect a faithful translation must emit.  */

Implementation References

bcx

xenia-rs interpreter body (frozen snapshot)
        PpcOpcode::bcx => {
            let bo = instr.bo();
            let bi = instr.bi();

            // Decrement CTR if needed
            if bo & 0b00100 == 0 {
                ctx.ctr = ctx.ctr.wrapping_sub(1);
            }

            let ctr_ok = (bo & 0b00100) != 0
                || (((ctx.ctr as u32) != 0) ^ ((bo & 0b00010) != 0));
            let cond_ok = (bo & 0b10000) != 0
                || (ctx.get_cr_bit(bi) == ((bo & 0b01000) != 0));

            if ctr_ok && cond_ok {
                let target = if instr.aa() {
                    instr.bd() as u32
                } else {
                    ctx.pc.wrapping_add(instr.bd() as u32)
                };
                if instr.lk() {
                    ctx.lr = (ctx.pc + 4) as u64;
                }
                ctx.pc = target;
            } else {
                if instr.lk() {
                    ctx.lr = (ctx.pc + 4) as u64;
                }
                ctx.pc += 4;
            }
        }

Special Cases & Edge Conditions

  • 14-bit signed displacement. BD is a 14-bit signed word-count, scaled by 4 — yielding a ±32 KiB byte range (2^15 … +2^15 4). For longer-range conditional control flow, compilers emit a short bc over an unconditional b.
  • CTR decrement happens before the test. BO[2]=0 decrements CTR first, then ctr_ok evaluates against the new value. The classic bdnz loop loops N times when CTR is initialised to N.
  • LR write is unconditional in xenia. Xenia writes LR ← CIA + 4 whenever LK=1, even on the not-taken path. This matches the PowerISA: bcl always sets LR regardless of branch outcome — exploited by bcl 20, 31, $+4 as a self-PC capture (PIC trick).
  • BO encoding — see bclrx.md for the full 5-bit table. bcx supports the full set, including CTR-only branches (bdnz, bdz).
  • Branch hint encoding. PPC overloads BO[4] as a static prediction hint: 0 = "predict not taken", 1 = "predict taken". The Xenon honours it for forward branches; backwards conditional branches are predicted taken regardless. Translators may ignore the hint.
  • Synchronisation. Marked sync — like all branches, bcx is context-synchronising. Trivial in interpretation; matters for JIT reorder windows.
  • No Rc. B-form has no record bit; the apparent Rc operand-table entry under "Status-Register Effects" is N/A here.

BO/BI encoding (compact table)

BO Effect Common simplified
0000z dec CTR, branch if CTR≠0 & ¬CR[BI] bdnzf BI, addr
0001z dec CTR, branch if CTR=0 & ¬CR[BI] bdzf BI, addr
0010y dec CTR, branch if CTR≠0 bdnz addr
0011y dec CTR, branch if CTR=0 bdz addr
0100z branch if ¬CR[BI] bf BI, addr (or bne/bge/...)
0101z branch if CR[BI] bt BI, addr (or beq/blt/...)
1z1zz branch always b addr (prefer plain b though)

Bit z is the prediction hint (0 = not taken, 1 = taken).

  • bx — unconditional displacement branch (24-bit range).
  • bclrx — branch conditional to LR (function return).
  • bcctrx — branch conditional to CTR (indirect call / dispatch).
  • crand, cror, … — combine multiple CR bits before a single bc.
  • mtctr, mfctr — set/get loop counter for bdnz/bdz.
  • sc — alternative control-flow exit.

Simplified Mnemonics

The bc mnemonic is rarely written directly; assemblers fold most uses into form-specific aliases:

Simplified Expansion
beq crN, addr bc 0b01100, 4·N+2, addr — branch if crN.EQ
bne crN, addr bc 0b00100, 4·N+2, addr — branch if crN.NE
blt crN, addr bc 0b01100, 4·N+0, addr — branch if crN.LT
bge crN, addr bc 0b00100, 4·N+0, addr — branch if crN.GE
bgt crN, addr bc 0b01100, 4·N+1, addr — branch if crN.GT
ble crN, addr bc 0b00100, 4·N+1, addr — branch if crN.LE
bso crN, addr bc 0b01100, 4·N+3, addr — branch on summary overflow
bns crN, addr bc 0b00100, 4·N+3, addr — branch on no SO
bdnz addr bc 0b10000, 0, addr — decrement CTR, branch if non-zero
bdz addr bc 0b10010, 0, addr — decrement CTR, branch if zero
bdnzt BI, addr combined CTR + CR test (rare)

When crN is omitted in disassembly, cr0 is implied.

IBM Reference