Files
xenia-rs/migration/project-root/ppc-manual/branch/bcx.md
MechaCat02 e6d43a23ac chore: add migration/ bundle for cross-machine setup
Bundles state that lives OUTSIDE the xenia-rs repo so a fresh clone on
another machine can be brought up to identical configuration via
migration/setup.sh:

  - claude-memory/             ~/.claude/projects/-home-fabi-RE-Project-Sylpheed/memory/
                               (103 files, 1.1 MB - MEMORY.md + every
                                project_xenia_rs_*.md from audits
                                addis_signext through audit-058)
  - project-root/dot-claude/   <project-root>/.claude/settings.json
                               (Stop hook + permissions)
  - project-root/ppc-manual/   <project-root>/ppc-manual/
                               (PowerPC reference docs, 397 files, 3.7 MB)
  - project-root/run-canary.sh <project-root>/run-canary.sh
  - README.md                  Human-readable setup checklist
  - setup.sh                   Idempotent installer (also reclones
                               xenia-canary at pinned HEAD 6de80dffe)
  - MANIFEST.md                Per-file mapping + per-file-not-bundled
                               restoration recipe

Excluded from bundle (not shippable via git):
  - Sylpheed ISO (7.8 GB; copyright; manual copy required)
  - sylpheed.db (395 MB; regenerable from XEX via analysis tooling)
  - target/ build artifacts (rebuild on target)
  - audit-runs probe firehoses (.log/.stdout/.stderr ~11 GB; rerun if needed)
  - audit-runs memory dumps (.bin ~4.5 GB; rerun audit-026/027/029 if needed)
  - xenia-canary checkout (setup.sh reclones from
    git.mc02.dev/fabi/Xenia-Canary.git at HEAD 6de80dffe)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:38:38 +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