; RISC-V Assembler extensions for RP2350 - Version 1 - 18th October 2024
; see http://www.ulisp.com/show?4Y5E
;

; Instruction formats

(defun bit13 (op1 op2 rs1 op3 rd)
  (emit32 '(7 5 5 3 5 7) op1 op2 (regno rs1) op3 (regno rd) #x13))

(defun bitimm5 (op1 imm5 rs1 op2 rd)
  (emit32 '(7 5 5 3 5 7) op1 (logand imm5 #x1f) (regno rs1) op2 (regno rd) #x13))

; Additional compressed formats

(defun $mul (rd rs1 rs2)
  (cond
   ((and (eq rd rs1) (cregp rd) (cregp rs2))
    (emit '(3 3 3 2 3 2) 4 7 (cregno rd) 2 (cregno rs2) 1))
   (t (muldiv rs2 rs1 0 rd #x33))))

(defun $sb (src imm &optional lst)
  (unless lst (setq lst imm imm 0))
  (cond
   ((and (cregp src) (cregp (car lst)) (<= 0 imm 3))
    (emit '(3 3 3 1 1 3 2) 4 2 (cregno (car lst)) (bits imm 0) (bits imm 1) (cregno src) 0))
   (t (store imm src (car lst) 0))))

(defun $sh (src imm &optional lst)
  (unless lst (setq lst imm imm 0))
  (cond
   ((and (cregp src) (cregp (car lst)) (or (= imm 0) (= im 2))
    (emit '(3 3 3 1 1 3 2) 4 3 (cregno (car lst)) 0 (bits imm 1) (cregno src) 0))
   (t (store imm src (car lst) 1)))))

; Add compressed formats to $lbu, $lh, and $lhu. No $lb compressed format
(defun $lbu (rd imm &optional lst)
  (unless lst (setq lst imm imm 0))
  (cond
   ((and (cregp rd) (cregp (car lst)) (<= 0 imm 3))
    (emit '(3 3 3 1 1 3 2) 4 0 (cregno (car lst)) (bits imm 0) (bits imm 1) (cregno rd) 0))
   (t (immed imm (car lst) 4 rd 3))))

(defun $lh (rd imm &optional lst)
  (unless lst (setq lst imm imm 0))
  (cond
   ((and (cregp rd) (cregp (car lst)) (or (= imm 0) (= im 2))
    (emit '(3 3 3 1 1 3 2) 4 1 (cregno (car lst)) 1 (bits imm 1) (cregno rd) 0))
   (t (immed imm (car lst) 1 rd 3)))))

(defun $lhu (rd imm &optional lst)
  (unless lst (setq lst imm imm 0))
  (cond
   ((and (cregp rd) (cregp (car lst)) (or (= imm 0) (= im 2))
    (emit '(3 3 3 1 1 3 2) 4 1 (cregno (car lst)) 0 (bits imm 1) (cregno rd) 0))
   (t (immed imm (car lst) 5 rd 3)))))

(defun $xori (rd rs1 imm)
  (cond
   ((and (eq rd rs1) (cregp rd) (= imm -1))
    (emit '(3 3 3 2 3 2) 4 7 (cregno rd) 3 5 1))
   (t (immed imm rs1 4 rd #x13))))

; New instructions

(defun $andn (rd rs1 rs2)
  (reg #x20 rs2 rs1 3 rd #x33))

(defun $bclr (rd rs1 rs2)
  (reg #x24 rs2 rs1 1 rd #x33))

(defun $bclri (rd rs1 imm5)
  (bitimm5 #x24 imm5 rs1 1 rd))

(defun $bext (rd rs1 rs2)
  (reg #x24 rs2 rs1 5 rd #x33))

(defun $bexti (rd rs1 imm5)
  (bitimm5 #x24 imm5 rs1 5 rd))

(defun $binv (rd rs1 rs2)
  (reg #x34 rs2 rs1 1 rd #x33))

(defun $binvi (rd rs1 imm5)
  (bitimm5 #x34 imm5 rs1 1 rd))

(defun $brev8 (rd rs1)
  (bit13 #x34 7 rs1 5 rd))

(defun $bset (rd rs1 rs2)
  (reg #x14 rs2 rs1 1 rd #x33))

(defun $bseti (rd rs1 imm5)
  (bitimm5 #x14 imm5 rs1 1 rd))

(defun $clz (rd rs1)
  (bit13 #x30 0 rs1 1 rd))

(defun $cpop (rd rs1)
  (bit13 #x30 2 rs1 1 rd))

(defun $ctz (rd rs1)
  (bit13 #x30 1 rs1 1 rd))

(defun $max (rd rs1 rs2)
  (reg #x05 rs2 rs1 6 rd #x33))

(defun $maxu (rd rs1 rs2)
  (reg #x05 rs2 rs1 7 rd #x33))

(defun $min (rd rs1 rs2)
  (reg #x05 rs2 rs1 4 rd #x33))

(defun $minu (rd rs1 rs2)
  (reg #x05 rs2 rs1 5 rd #x33))

(defun $orc.b (rd rs1)
  (bit13 #x14 7 rs1 5 rd))

(defun $orn (rd rs1 rs2)
  (reg #x20 rs2 rs1 5 rd #x33))

(defun $pack (rd rs1 rs2)
  (reg #x04 rs2 rs1 4 rd #x33))

(defun $packh (rd rs1 rs2)
  (reg #x04 rs2 rs1 7 rd #x33))

(defun $rev8 (rd rs1)
  (bit13 #x34 #x18 rs1 5 rd))

(defun $rol (rd rs1 rs2)
  (reg #x30 rs2 rs1 1 rd #x33))

(defun $ror (rd rs1 rs2)
  (reg #x30 rs2 rs1 5 rd #x33))

(defun $rori (rd rs1 imm5)
  (bitimm5 #x30 imm5 rs1 5 rd))

(defun $sext.b (rd rs1)
  (bit13 #x30 #x04 rs1 1 rd))

(defun $sext.h (rd rs1)
  (bit13 #x30 #x05 rs1 1 rd))

(defun $unzip (rd rs1)
  (bit13 #x04 #x0f rs1 5 rd))

(defun $xnor (rd rs1 rs2)
  (reg #x20 rs2 rs1 4 rd #x33))

(defun $zext.b (rd rs1)
  ($andi rd rs1 #xff)))

(defun $zext.h (rd rs1)
  (emit32 '(7 5 5 3 5 7) #x04 0 (regno rs1) 4 (regno rd) #x33))

(defun $zip (rd rs1)
  (bit13 #x04 #x0f rs1 1 rd))


