(herald (assembler ppc_branch) (env t (assembler as_open) (assembler ppc_machine) (assembler ppc_format)) (syntax-table tas-ppc-syntax-table)) ;;;; PowerPC Instruction Set: Branches ;;; Copyright (C) 2006, Taylor Campbell. ;;; All rights reserved. ;;; See the LICENCE file for details. ;;; (These formats are all specialized for branches, which is why they ;;; aren're listed in ppc_format.t.) ;;; Branch (unconditional) (define-fg (ppc/*b tag abs-bit link-bit suffix) (printer "b~A ~G" suffix tag) (local pc) (fields (mark pc) (fixed 6 #b010010) (fixed 24 (fixnum-ashr (from pc tag) 5)) (fixed 1 abs-bit) (fixed 1 link-bit))) (define-ppc-op (b tag) (ppc/*b tag 0 0 "")) (define-ppc-op (ba tag) (ppc/*b tag 1 0 "a")) (define-ppc-op (bl tag) (ppc/*b tag 0 1 "l")) (define-ppc-op (bla tag) (ppc/*b tag 1 1 "la")) ;;; Branch Conditional (define-fg (ppc/*bc op predict? cr-idx tag abs-bit link-bit suffix) (printer "bc~A~A #b~B,~A,~G" suffix (if predict? ",p" "") op cr-idx tag) (local pc) (fields (mark pc) (fixed 6 #b010000) (fixed 4 op) (fixed 1 (if predict? 1 0)) (fixed 5 cr-idx) ;; Shift of 5: FROM gives us a bit count, but we want the ;; displacement in words (32 = 2^5 bits). (fixed 14 (fixnum-ashr (from pc tag) 5)) (fixed 1 abs-bit) (fixed 1 link-bit))) (define-ppc-op (bc op p? cr-idx tag) (ppc/*bc op p? cr-idx tag 0 0 "")) (define-ppc-op (bca op p? cr-idx tag) (ppc/*bc op p? cr-idx tag 1 0 "a")) (define-ppc-op (bcl op p? cr-idx tag) (ppc/*bc op p? cr-idx tag 0 1 "l")) (define-ppc-op (bcla op p? cr-idx tag) (ppc/*bc op p? cr-idx tag 1 1 "la")) ;;; Branch Conditional to Count/Link Register (define-fg (ppc/bcr op predict? cr-idx counter-bit link-bit) (print (port) (labels (((print-name) (write-string port (if (fx-zero? counter-bit) "l" "ct")) (write-char port #\r) (if (not (fx-zero? link-bit)) (write-char port #\l)) (if predict? (write-string port ",p")))) (write-char port #\b) (if (fx= op bc-op/always) (print-name) (block (write-char port #\c) (print-name) (format port " #b~B,~D" op cr-idx))))) (fields (fixed 6 #b010011) (fixed 4 op) (fixed 1 (if predict? 1 0)) (fixed 5 cr-idx) (fixed 5 0) (fixed 1 counter-bit) ;If 1, use counter; if 0, link. (fixed 9 #b000010000) (fixed 1 link-bit))) ;If 1, set link register. (define-ppc-op (bclr op p? cr-idx) (ppc/bcr op p? cr-idx 0 0)) (define-ppc-op (bclrl op p? cr-idx) (ppc/bcr op p? cr-idx 0 1)) (define-ppc-op (bcctr op p? cr-idx) (ppc/bcr op p? cr-idx 1 0)) (define-ppc-op (bcctrl op p? cr-idx) (ppc/bcr op p? cr-idx 1 1)) ;;; Branch to Count/Link Register (unconditional) (define-ppc-op (blr) (ppc/bclr bc-op/always '#f 0)) (define-ppc-op (blrl) (ppc/bclrl bc-op/always '#f 0)) (define-ppc-op (bctr) (ppc/bcctr bc-op/always '#f 0)) (define-ppc-op (bctrl) (ppc/bcctrl bc-op/always '#f 0)) ;;; These branch condition op constructors all integrate nicely. (define-integrable (make-bc-op ignore-cond? negate-cond? counter-? counter=0?) (assemble-fixnum (bool ignore-cond?) (bool negate-cond?) (bool (not counter-?)) (bool counter=0?))) (define-integrable (make-cr-bc-op true?) ;; Don't ignore the condition, maybe negate, don't decrement the ;; counter, and whether the counter is zero or not is irrelevant. (make-bc-op '#f true? '#f '#f)) (define-integrable (make-bc-op/counter- counter=0?) ;; Ignore the condition, the condition is irrelevant, decrement the ;; counter, and test either whether the counter is zero or whether it ;; is not zero. (make-bc-op '#t '#f '#t counter=0?)) (define-integrable (make-cr-bc-op/counter- true? counter=0?) ;; Don't ignore the condition, maybe negate, decrement the counter, ;; and test either whether the counter is zero or whether it is not ;; zero. (make-bc-op '#f true? '#t counter=0?)) (define-constant bc-op/always #b1010) (define-integrable (fx-bit-set? bit n) (not (fx-zero? (fx-and n (fx-ashl 1 bit))))) (define (reverse-bc-op op) (if (fx-bit-set? 3 op) ;Ignore the condition? (if (fx-bit-set? 1 op) ;Ignore the counter? op ;Nothing to reverse. (fx-xor op #b0001)) ;Flip CTR=0? (if (fx-bit-set? 1 op) ;Ignore the counter? (fx-xor op #b0100) ;Flip truth (fx-xor op #b0101)))) ;Flip truth & CTR=0? (define-integrable (make-ppc-jump-op branch-op bc-op predict? cr-index) (vector branch-op bc-op predict? cr-index)) (define-integrable (make-ppc-jabs-op branch-op) branch-op) (set (machine-cond-branch powerpc) (lambda (jop tag) (if (vector? jop) ((vref jop 0) (vref jop 1) (vref jop 2) (vref jop 3) tag) (jop tag)))) (set (machine-uncond-branch powerpc) ppc/b) (set (machine-reverse-jump powerpc) (lambda (jop) (vector (vref jop 0) (reverse-bc-op (vref jop 1)) (not (vref jop 1)) (vref jop 2))))