(herald (assembler ppc_arith) (env t (assembler as_open) (assembler ppc_machine) (assembler ppc_format)) (syntax-table tas-ppc-syntax-table)) ;;;; PowerPC Instruction Set: Integer Arithmetic Instructions ;;; Copyright (C) 2006, Taylor Campbell. ;;; All rights reserved. ;;; See the LICENCE file for details. ;;; ---------------- ;;; Integer instructions ;;; Addition & subtraction (define-arith-ops add #b100001010) ;Add (define-arith-ops addc #b000001010) ;Add Carrying (define-arith-ops adde #b010001010) ;Add Extended (define-arith-ops subf #b000101000) ;Subtract (rA) From (rB) (define-arith-ops subfc #b000001000) ;Subtract From Carrying (define-arith-ops subfe #b010001000) ;Subtract From Extended (define-arith-imm-op addi #b001110 ;Add Immediate (lambda (port rD rA imm) (cond ((or (eq? rA 0) (eq? rA ppc-reg/zero)) (format port "li ~A,#x~X" rD imm)) ((fixnum-negative? imm) (format port "subi ~A,~A,#x~X" rD rA (fx-negate imm))) (else (format port "addi ~A,~A,#x~X" rD rA imm))))) (define-ppc-op (li rD value) ;Load Immediate (ppc/addi rD 0 value)) (define-ppc-op (subi rD rA value) ;Subtract Immediate (ppc/addi rD rA (fx-negate value))) (define-arith-imm-op addic #b001100 ;Add Immediate Carrying (lambda (port rD rA imm) (if (fixnum-negative? imm) (format port "subic ~A,~A,#x~X" rA rD (fx-negate imm)) (format port "addic ~A,~A,#x~X" rA rD imm)))) (define-ppc-op (subic rD rA value) ;Subtract Imm Carrying (ppc/addic rD rA (fx-negate value))) (define-arith-imm-op subfic #b000100) ;Subtract From Imm Carrying (?) (define-arith-imm-op addic. #b001101 ;Add Imm Carrying & Record (lambda (port rD rA imm) (if (fixnum-negative? imm) (format port "subic. ~A,~A,#x~X" rA rD (fx-negate imm)) (format port "addic. ~A,~A,#x~X" rA rD imm)))) (define-ppc-op (subic. rD rA value) ;Sub Imm Carrying & Record (ppc/addic. rD rA (fx-negate value))) (define-arith-imm-op addis #b001111 ;Add Immediate Shifted (lambda (port rD rA imm) (cond ((or (eq? rA 0) (eq? rA ppc-reg/zero)) (format port "lis ~A,#x~X" rD imm)) ((fixnum-negative? imm) (format port "subis ~A,~A,#x~X" rD rA (fx-negate imm))) (else (format port "addis ~A,~A,#x~X" rD rA imm))))) (define-ppc-op (lis rD value) ;Load Immediate Shifted (ppc/addis rD 0 value)) (define-ppc-op (subis rD rA value) ;Subtract Immediate Shifted (ppc/addis rD 0 (fx-negate value))) (define-local-syntax (define-arith-unops id secondary) `(DEFINE-ARITH-OPS ,id ,secondary DEFINE-ARITH-UNOP)) (define-arith-unops addme #b011101010) ;Add to Minus one Extended (define-arith-unops addze #b011001010) ;Add to Zero Extended (define-arith-unops subfme #b011101000) ;Sub From Minus one Extended (define-arith-unops subfze #b011001000) ;Sub From Zero Extended (define-arith-unops neg #b001101000) ;Negate ;;; Division & multiplication (define-arith-ops divw #b111101011) ;Divide Word (define-arith-ops divwu #b111001011) ;Divide Word Unsigned (define-arith-ops mullw #b011101011) ;Multiply Low Word (define-arith-op* mulhw #b00010010110) ;Multiply High Word (define-arith-op* mulhw. #b00010010111) (define-arith-op* mulhwu #b00000010110) ;Multiply High Word Unsigned (define-arith-op* mulhwu. #b00000010111) (define-arith-imm-op mulli #b001001) ;Multiply Low Immediate ;;; Comparison (define-ppc-op (cmp cr-field rA operand) (cond ((register? operand) (ppc/cmp-format #b011111 cr-field rA (ppc/cmp-reg-operand operand 0) "cmp")) (((fixnum-of-bits? 16) operand) (ppc/cmp-format #b001011 cr-field rA (ppc/cmp-imm-operand operand) "cmpi")) (else (ppc/cmp cr-field rA (error "illegal PPC comparison operand ~S" operand))))) (define-ppc-op (cmpl cr-field rA operand) (cond ((register? operand) (ppc/cmp-format #b011111 cr-field rA (ppc/cmp-reg-operand operand 32) "cmpl")) (((fixnum-of-bits? 16) operand) (ppc/cmp-format #b001010 cr-field rA (ppc/cmp-imm-operand operand) "cmpli")) (else (ppc/cmpl cr-field rA (error "illegal PPC comparison operand ~S" operand))))) ;;; Logical (define-arith-op* and #b00000111000) ;Bitwise AND (define-arith-op* and. #b00000111001) (define-arith-op* andc #b00001111000) ;AND with Complement (define-arith-op* andc. #b00001111001) (define-arith-imm-op andi #b011100) ;AND with Immediate (define-arith-imm-op andic #b011101) ;AND with Immediate Shifted (define-arith-op* nand #b01110111000) ;Negation of AND (define-arith-op* nand. #b01110111001) (define-arith-op* or #b01101111000) ;Bitwise inclusive OR (define-arith-op* or. #b01101111001) (define-ppc-op (mr rD rS) (ppc/or rD rS rS)) (define-arith-op* orc #b01100111000) ;OR with Complement (define-arith-op* orc. #b01100111001) (define-arith-imm-op ori #b0011000) ;OR with Immediate (define-arith-imm-op oris #b0011001) ;OR with Immediate Shifted (define-ppc-op (nop) (ppc/ori ppc-reg/zero 0 0)) (define-arith-op* nor #b00001111100) ;Negation of inclusive OR (define-arith-op* nor. #b00001111101) (define-ppc-op (not rD rS) (ppc/nor rD rS rS)) (define-arith-op* xor #b01001111000) ;Bitwise exclusive OR (define-arith-op* xor. #b01001111001) (define-arith-imm-op xori #b0011010) ;XOR with Immediate (define-arith-imm-op xoris #b0011011) ;XOR with Immediate Shifted (define-arith-op* eqv #b01000111000) ;Bitwise EQV (define-arith-op* eqv. #b01000111001) (define-arith-op* cntlzw #b00000110100) ;Count Leading Zeros in Word (define-arith-op* cntlzw. #b00000110101) (define-arith-op* extsb #b11101110100) ;Extend Sign Byte (define-arith-op* extsb. #b11101110101) (define-arith-op* extsh #b11101010100) ;Extend Sign Halfword (define-arith-op* extsh. #b11101010101) ;;; Rotation (define-fg (ppc/rotation opcode rD rS shift begin end rc-bit name) (printer "~A ~A,~A,~D,~D,~D" name rD rS shift begin end) (fields (fixed 6 opcode) (fixed 5 (register-code rD)) (fixed 5 (register-code rS)) (fixed 5 shift) (fixed 5 begin) (fixed 5 end) (fixed 1 rc-bit))) ; Rotate Left Word Immediate then Mask Insert (define-ppc-op (rlwimi rD rS shift begin end) (ppc/rotation #b010100 rD rS shift begin end 0 "rlwimi")) (define-ppc-op (rlwimi. rD rS shift begin end) (ppc/rotation #b010100 rD rS shift begin end 1 "rlwimi.")) ; Rotate Left Word Immediate then AND with Mask (define-ppc-op (rlwinm rD rS shift begin end) (ppc/rotation #b010101 rD rS shift begin end 0 "rlwinm")) (define-ppc-op (rlwinm. rD rS shift begin end) (ppc/rotation #b010101 rD rS shift begin end 1 "rlwinm.")) ; Rotate Left Word then AND with Mask (define-ppc-op (rlwnm rD rA rB begin end) (ppc/rotation #b010111 rD rA (register-code rB) begin end 0 "rlwnm")) (define-ppc-op (rlwnm. rD rA rB begin end) (ppc/rotation #b010111 rD rA (register-code rB) begin end 1 "rlwnm.")) ;;; Shifting (define-fg (ppc/shift rD rA rS secondary name) (printer "~A ~A,~A,~G" name rD rA shift-field) (fields (fixed 6 #b011111) (fixed 5 (register-code rD)) ;Destination (fixed 5 (register-code rA)) ;Argument (fixed 5 (register-code rS)) ;Shift (fixed 11 secondary))) (define-local-syntax (define-shift-op id secondary) (let ((id. (concatenate-symbol id "."))) `(BLOCK (DEFINE-PPC-OP (,id rD rA rS) (PPC/SHIFT rD rA rS ,secondary ',(id->string id))) (DEFINE-PPC-OP (,id. rD rA rS) (PPC/SHIFT rD rA rS ,secondary ',(id->string id.)))))) (define-shift-op slw #b00000011000) ;Shift Left Word (define-shift-op sraw #b11000110000) ;Shift Right Algebraic Word (define-shift-op srw #b10000110000) ;Shift Right Word (define-fg (ppc/*srawi rD rA shift rc) ;Shift Right Alg. Word Imm. (printer "srawi~A ~A,~A,~D" (if (fx-zero? rc) "" ".") rD rA shift) (fields (fixed 6 011111) (fixed 5 (register-code rD)) (fixed 5 (register-code rA)) (fixed 5 shift) (fixed 10 #b1100111000) (fixed 1 rc))) (define-ppc-op (srawi rD rA shift) (ppc/*srawi rD rA shift 0)) (define-ppc-op (srawi. rD rA shift) (ppc/*srawi rD rA shift 1))