|
|
; Ubicom IP2K CPU description. -*- Scheme -*- |
|
|
; Copyright (C) 2002, 2009, 2011 Free Software Foundation, Inc. |
|
|
; |
|
|
; Contributed by Red Hat Inc; |
|
|
; |
|
|
; This file is part of the GNU Binutils. |
|
|
; |
|
|
; This program is free software; you can redistribute it and/or modify |
|
|
; it under the terms of the GNU General Public License as published by |
|
|
; the Free Software Foundation; either version 3 of the License, or |
|
|
; (at your option) any later version. |
|
|
; |
|
|
; This program is distributed in the hope that it will be useful, |
|
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
; GNU General Public License for more details. |
|
|
; |
|
|
; You should have received a copy of the GNU General Public License |
|
|
; along with this program; if not, write to the Free Software |
|
|
; Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
|
|
; MA 02110-1301, USA. |
|
|
|
|
|
(define-rtl-version 0 8) |
|
|
|
|
|
(include "simplify.inc") |
|
|
|
|
|
; define-arch must appear first |
|
|
|
|
|
(define-arch |
|
|
(name ip2k) ; name of cpu family |
|
|
(comment "Ubicom IP2000 family") |
|
|
(default-alignment aligned) |
|
|
(insn-lsb0? #t) |
|
|
(machs ip2022 ip2022ext) |
|
|
(isas ip2k) |
|
|
) |
|
|
|
|
|
; Attributes. |
|
|
|
|
|
(define-attr |
|
|
(for insn) |
|
|
(type boolean) |
|
|
(name EXT-SKIP-INSN) |
|
|
(comment "instruction is a PAGE, LOADL, LOADH or BREAKX instruction") |
|
|
) |
|
|
|
|
|
(define-attr |
|
|
(for insn) |
|
|
(type boolean) |
|
|
(name SKIPA) |
|
|
(comment "instruction is a SKIP instruction") |
|
|
) |
|
|
|
|
|
; Instruction set parameters. |
|
|
|
|
|
(define-isa |
|
|
(name ip2k) |
|
|
(comment "Ubicom IP2000 ISA") |
|
|
|
|
|
(default-insn-word-bitsize 16) |
|
|
(default-insn-bitsize 16) |
|
|
(base-insn-bitsize 16) |
|
|
) |
|
|
|
|
|
; Cpu family definitions. |
|
|
|
|
|
|
|
|
(define-cpu |
|
|
; cpu names must be distinct from the architecture name and machine names. |
|
|
(name ip2kbf) |
|
|
(comment "Ubicom IP2000 Family") |
|
|
(endian big) |
|
|
(word-bitsize 16) |
|
|
) |
|
|
|
|
|
(define-mach |
|
|
(name ip2022) |
|
|
(comment "Ubicom IP2022") |
|
|
(cpu ip2kbf) |
|
|
) |
|
|
|
|
|
(define-mach |
|
|
(name ip2022ext) |
|
|
(comment "Ubicom IP2022 extended") |
|
|
(cpu ip2kbf) |
|
|
) |
|
|
|
|
|
|
|
|
; Model descriptions. |
|
|
|
|
|
(define-model |
|
|
(name ip2k) (comment "VPE 2xxx") (attrs) |
|
|
(mach ip2022ext) |
|
|
|
|
|
(unit u-exec "Execution Unit" () |
|
|
1 1 ; issue done |
|
|
() ; state |
|
|
() ; inputs |
|
|
() ; outputs |
|
|
() ; profile action (default) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
; FIXME: It might simplify things to separate the execute process from the |
|
|
; one that updates the PC. |
|
|
|
|
|
; Instruction fields. |
|
|
; |
|
|
; Attributes: |
|
|
; XXX: what VPE attrs |
|
|
; PCREL-ADDR: pc relative value (for reloc and disassembly purposes) |
|
|
; ABS-ADDR: absolute address (for reloc and disassembly purposes?) |
|
|
; RESERVED: bits are not used to decode insn, must be all 0 |
|
|
; RELOC: there is a relocation associated with this field (experiment) |
|
|
|
|
|
|
|
|
(dnf f-imm8 "imm8" () 7 8) |
|
|
(dnf f-reg "reg" (ABS-ADDR) 8 9) |
|
|
(dnf f-addr16cjp "addr16cjp" (ABS-ADDR) 12 13) |
|
|
(dnf f-dir "dir" () 9 1) |
|
|
(dnf f-bitno "bit number" () 11 3) |
|
|
(dnf f-op3 "op3" () 15 3) |
|
|
(dnf f-op4 "op4" () 15 4) |
|
|
(dnf f-op4mid "op4mid" () 11 4) |
|
|
(dnf f-op6 "op6" () 15 6) |
|
|
(dnf f-op8 "op8" () 15 8) |
|
|
(dnf f-op6-10low "op6-10low" () 9 10) |
|
|
(dnf f-op6-7low "op6-7low" () 9 7) |
|
|
(dnf f-reti3 "reti3" () 2 3) |
|
|
(dnf f-skipb "sb/snb" (ABS-ADDR) 12 1) |
|
|
(dnf f-page3 "page3" () 2 3) |
|
|
;(define-ifield (name f-page3) (comment "page3") (attrs) (start 2) (length 3) |
|
|
; (encode (value pc) (srl WI value 13)) |
|
|
; (decode (value pc) (sll WI value 13)) |
|
|
;) |
|
|
; To fix the page/call asymmetry |
|
|
;(define-ifield (name f-page3) (comment "page3") (attrs) (start 2) (length 3) |
|
|
; (encode (value pc) (srl WI value 13)) |
|
|
; (decode (value pc) (sll WI value 13)) |
|
|
;) |
|
|
|
|
|
|
|
|
|
|
|
; Enums. |
|
|
|
|
|
; insn-op6: bits 15-10 |
|
|
(define-normal-insn-enum insn-op6 "op6 enums" () OP6_ f-op6 |
|
|
(OTHER1 OTHER2 SUB DEC OR AND XOR ADD |
|
|
TEST NOT INC DECSZ RR RL SWAP INCSZ |
|
|
CSE POP SUBC DECSNZ MULU MULS INCSNZ ADDC |
|
|
- - - - - - - - |
|
|
- - - - - - - - |
|
|
- - - - - - - - |
|
|
- - - - - - - - |
|
|
- - - - - - - - |
|
|
) |
|
|
) |
|
|
|
|
|
; insn-dir: bit 9 |
|
|
(define-normal-insn-enum insn-dir "dir enums" () DIR_ f-dir |
|
|
; This bit specifies the polarity of many two-operand instructions: |
|
|
; TO_W writes result to W regiser (eg. ADDC W,$fr) |
|
|
; NOTTO_W writes result in general register (eg. ADDC $fr,W) |
|
|
(TO_W NOTTO_W) |
|
|
) |
|
|
|
|
|
|
|
|
; insn-op4: bits 15-12 |
|
|
(define-normal-insn-enum insn-op4 "op4 enums" () OP4_ f-op4 |
|
|
(- - - - - - - LITERAL |
|
|
CLRB SETB SNB SB - - - - |
|
|
) |
|
|
) |
|
|
|
|
|
; insn-op4mid: bits 11-8 |
|
|
; used for f-op4=LITERAL |
|
|
(define-normal-insn-enum insn-op4mid "op4mid enums" () OP4MID_ f-op4mid |
|
|
(LOADH_L LOADL_L MULU_L MULS_L PUSH_L - CSNE_L CSE_L |
|
|
RETW_L CMP_L SUB_L ADD_L MOV_L OR_L AND_L XOR_L) |
|
|
) |
|
|
|
|
|
; insn-op3: bits 15-13 |
|
|
(define-normal-insn-enum insn-op3 "op3 enums" () OP3_ f-op3 |
|
|
(- - - - - - CALL JMP) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
; Hardware pieces. |
|
|
|
|
|
; Bank-relative general purpose registers |
|
|
|
|
|
; (define-pmacro (build-reg-name n) (.splice (.str "$" n) n)) |
|
|
|
|
|
(define-keyword |
|
|
(name register-names) |
|
|
(enum-prefix H-REGISTERS-) |
|
|
(values |
|
|
; These are the "Special Purpose Registers" that are not reserved |
|
|
("ADDRSEL" #x2) ("ADDRX" #x3) |
|
|
("IPH" #x4) ("IPL" #x5) ("SPH" #x6) ("SPL" #x7) |
|
|
("PCH" #x8) ("PCL" #x9) ("WREG" #xA) ("STATUS" #xB) |
|
|
("DPH" #xC) ("DPL" #xD) ("SPDREG" #xE) ("MULH" #xF) |
|
|
("ADDRH" #x10) ("ADDRL" #x11) ("DATAH" #x12) ("DATAL" #x13) |
|
|
("INTVECH" #x14) ("INTVECL" #x15) ("INTSPD" #x16) ("INTF" #x17) |
|
|
("INTE" #x18) ("INTED" #x19) ("FCFG" #x1A) ("TCTRL" #x1B) |
|
|
("XCFG" #x1C) ("EMCFG" #x1D) ("IPCH" #x1E) ("IPCL" #x1F) |
|
|
("RAIN" #x20) ("RAOUT" #x21) ("RADIR" #x22) ("LFSRH" #x23) |
|
|
("RBIN" #x24) ("RBOUT" #x25) ("RBDIR" #x26) ("LFSRL" #x27) |
|
|
("RCIN" #x28) ("RCOUT" #x29) ("RCDIR" #x2A) ("LFSRA" #x2B) |
|
|
("RDIN" #x2C) ("RDOUT" #x2D) ("RDDIR" #x2E) |
|
|
("REIN" #x30) ("REOUT" #x31) ("REDIR" #x32) |
|
|
("RFIN" #x34) ("RFOUT" #x35) ("RFDIR" #x36) |
|
|
("RGOUT" #x39) ("RGDIR" #x3A) |
|
|
("RTTMR" #x40) ("RTCFG" #x41) ("T0TMR" #x42) ("T0CFG" #x43) |
|
|
("T1CNTH" #x44) ("T1CNTL" #x45) ("T1CAP1H" #x46) ("T1CAP1L" #x47) |
|
|
("T1CAP2H" #x48) ("T1CMP2H" #x48) ("T1CAP2L" #x49) ("T1CMP2L" #x49) ; note aliases |
|
|
("T1CMP1H" #x4A) ("T1CMP1L" #x4B) |
|
|
("T1CFG1H" #x4C) ("T1CFG1L" #x4D) ("T1CFG2H" #x4E) ("T1CFG2L" #x4F) |
|
|
("ADCH" #x50) ("ADCL" #x51) ("ADCCFG" #x52) ("ADCTMR" #x53) |
|
|
("T2CNTH" #x54) ("T2CNTL" #x55) ("T2CAP1H" #x56) ("T2CAP1L" #x57) |
|
|
("T2CAP2H" #x58) ("T2CMP2H" #x58) ("T2CAP2L" #x59) ("T2CMP2L" #x59) ; note aliases |
|
|
("T2CMP1H" #x5A) ("T2CMP1L" #x5B) |
|
|
("T2CFG1H" #x5C) ("T2CFG1L" #x5D) ("T2CFG2H" #x5E) ("T2CFG2L" #x5F) |
|
|
("S1TMRH" #x60) ("S1TMRL" #x61) ("S1TBUFH" #x62) ("S1TBUFL" #x63) |
|
|
("S1TCFG" #x64) ("S1RCNT" #x65) ("S1RBUFH" #x66) ("S1RBUFL" #x67) |
|
|
("S1RCFG" #x68) ("S1RSYNC" #x69) ("S1INTF" #x6A) ("S1INTE" #x6B) |
|
|
("S1MODE" #x6C) ("S1SMASK" #x6D) ("PSPCFG" #x6E) ("CMPCFG" #x6F) |
|
|
("S2TMRH" #x70) ("S2TMRL" #x71) ("S2TBUFH" #x72) ("S2TBUFL" #x73) |
|
|
("S2TCFG" #x74) ("S2RCNT" #x75) ("S2RBUFH" #x76) ("S2RBUFL" #x77) |
|
|
("S2RCFG" #x78) ("S2RSYNC" #x79) ("S2INTF" #x7A) ("S2INTE" #x7B) |
|
|
("S2MODE" #x7C) ("S2SMASK" #x7D) ("CALLH" #x7E) ("CALLL" #x7F)) |
|
|
) |
|
|
|
|
|
(define-hardware |
|
|
(name h-spr) |
|
|
(comment "special-purpose registers") |
|
|
(type register QI (128)) |
|
|
(get (index) (c-call QI "get_spr" index )) |
|
|
(set (index newval) (c-call VOID "set_spr" index newval )) |
|
|
) |
|
|
|
|
|
|
|
|
;;(define-hardware |
|
|
;; (name h-gpr-global) |
|
|
;; (comment "gpr registers - global") |
|
|
;; (type register QI (128)) |
|
|
;;) |
|
|
|
|
|
; The general register |
|
|
|
|
|
(define-hardware |
|
|
(name h-registers) |
|
|
(comment "all addressable registers") |
|
|
(attrs VIRTUAL) |
|
|
(type register QI (512)) |
|
|
(get (index) (c-call QI "get_h_registers" index )) |
|
|
(set (index newval) (c-call VOID "set_h_registers" index newval )) |
|
|
) |
|
|
|
|
|
; The hardware stack. |
|
|
; Use {push,pop}_pc_stack c-calls to operate on this hardware element. |
|
|
|
|
|
(define-hardware |
|
|
(name h-stack) |
|
|
(comment "hardware stack") |
|
|
(type register UHI (16)) |
|
|
) |
|
|
|
|
|
(dsh h-pabits "page bits" () (register QI)) |
|
|
(dsh h-zbit "zero bit" () (register BI)) |
|
|
(dsh h-cbit "carry bit" () (register BI)) |
|
|
(dsh h-dcbit "digit-carry bit" () (register BI)) |
|
|
(dnh h-pc "program counter" (PC PROFILE) (pc) () () ()) |
|
|
|
|
|
|
|
|
; Operands |
|
|
|
|
|
(define-operand (name addr16cjp) (comment "13-bit address") (attrs) |
|
|
(type h-uint) (index f-addr16cjp) (handlers (parse "addr16_cjp") (print "dollarhex_cj"))) ; overload lit8 printer |
|
|
(define-operand (name fr) (comment "register") (attrs) |
|
|
(type h-registers) (index f-reg) (handlers (parse "fr") (print "fr"))) |
|
|
(define-operand (name lit8) (comment "8-bit signed literal") (attrs) |
|
|
(type h-sint) (index f-imm8) (handlers (parse "lit8") (print "dollarhex8"))) |
|
|
(define-operand (name bitno) (comment "bit number") (attrs) |
|
|
(type h-uint) (index f-bitno) (handlers (parse "bit3")(print "decimal"))) |
|
|
(define-operand (name addr16p) (comment "page number") (attrs) |
|
|
(type h-uint) (index f-page3) (handlers (parse "addr16_cjp") (print "dollarhex_p"))) |
|
|
(define-operand (name addr16h) (comment "high 8 bits of address") (attrs) |
|
|
(type h-uint) (index f-imm8) (handlers (parse "addr16") (print "dollarhex_addr16h"))) |
|
|
(define-operand (name addr16l) (comment "low 8 bits of address") (attrs) |
|
|
(type h-uint) (index f-imm8) (handlers (parse "addr16") (print "dollarhex_addr16l"))) |
|
|
(define-operand (name reti3) (comment "reti flags") (attrs) |
|
|
(type h-uint) (index f-reti3) (handlers (print "dollarhex"))) |
|
|
(dnop pabits "page bits" () h-pabits f-nil) |
|
|
(dnop zbit "zero bit" () h-zbit f-nil) |
|
|
(dnop cbit "carry bit" () h-cbit f-nil) |
|
|
(dnop dcbit "digit carry bit" () h-dcbit f-nil) |
|
|
;;(dnop bank "bank register" () h-bank-no f-nil) |
|
|
|
|
|
(define-pmacro w (reg h-spr #x0A)) |
|
|
(define-pmacro mulh (reg h-spr #x0F)) |
|
|
(define-pmacro dph (reg h-spr #x0C)) |
|
|
(define-pmacro dpl (reg h-spr #x0D)) |
|
|
(define-pmacro sph (reg h-spr #x06)) |
|
|
(define-pmacro spl (reg h-spr #x07)) |
|
|
(define-pmacro iph (reg h-spr #x04)) |
|
|
(define-pmacro ipl (reg h-spr #x05)) |
|
|
(define-pmacro addrh (reg h-spr #x10)) |
|
|
(define-pmacro addrl (reg h-spr #x11)) |
|
|
|
|
|
|
|
|
|
|
|
; Pseudo-RTL for DC flag calculations |
|
|
; "DC" = "digit carry", ie carry between nibbles |
|
|
(define-pmacro (add-dcflag a b c) |
|
|
(add-cflag (sll QI a 4) (sll QI b 4) c) |
|
|
) |
|
|
|
|
|
(define-pmacro (sub-dcflag a b c) |
|
|
(sub-cflag (sll QI a 4) (sll QI b 4) c) |
|
|
) |
|
|
|
|
|
; Check to see if an fr is one of IPL, SPL, DPL, ADDRL, PCL. |
|
|
(define-pmacro (LregCheck isLreg fr9bit) |
|
|
(sequence() |
|
|
(set isLreg #x0) ;; Assume it's not an Lreg |
|
|
(if (or (or (eq fr9bit #x5) (eq fr9bit #x7)) |
|
|
(or (eq fr9bit #x9) |
|
|
(or (eq fr9bit #xd) (eq fr9bit #x11)))) |
|
|
(set isLreg #x1) |
|
|
) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
; Instructions, in order of the "Instruction Set Map" table on |
|
|
; pp 19-20 of IP2022 spec V1.09 |
|
|
|
|
|
(dni jmp "Jump" |
|
|
() |
|
|
"jmp $addr16cjp" |
|
|
(+ OP3_JMP addr16cjp) |
|
|
(set pc (or (sll pabits 13) addr16cjp)) |
|
|
() |
|
|
) |
|
|
|
|
|
; note that in call, we push pc instead of pc + 1 because the ip2k increments |
|
|
; the pc prior to execution of the instruction |
|
|
(dni call "Call" |
|
|
() |
|
|
"call $addr16cjp" |
|
|
(+ OP3_CALL addr16cjp) |
|
|
(sequence () |
|
|
(c-call "push_pc_stack" pc) |
|
|
(set pc (or (sll pabits 13) addr16cjp))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni sb "Skip if bit set" |
|
|
() |
|
|
"sb $fr,$bitno" |
|
|
(+ OP4_SB bitno fr) |
|
|
(if (and fr (sll 1 bitno)) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni snb "Skip if bit clear" |
|
|
() |
|
|
"snb $fr,$bitno" |
|
|
(+ OP4_SNB bitno fr) |
|
|
(if (not (and fr (sll 1 bitno))) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni setb "Set bit" |
|
|
() |
|
|
"setb $fr,$bitno" |
|
|
(+ OP4_SETB bitno fr) |
|
|
(set fr (or fr (sll 1 bitno))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni clrb "Clear bit" |
|
|
() |
|
|
"clrb $fr,$bitno" |
|
|
(+ OP4_CLRB bitno fr) |
|
|
(set fr (and fr (inv (sll 1 bitno)))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni xorw_l "XOR W,literal" |
|
|
() |
|
|
"xor W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_XOR_L lit8) |
|
|
(sequence () |
|
|
(set w (xor w lit8)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni andw_l "AND W,literal" |
|
|
() |
|
|
"and W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_AND_L lit8) |
|
|
(sequence () |
|
|
(set w (and w lit8)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni orw_l "OR W,literal" |
|
|
() |
|
|
"or W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_OR_L lit8) |
|
|
(sequence () |
|
|
(set w (or w lit8)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni addw_l "ADD W,literal" |
|
|
() |
|
|
"add W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_ADD_L lit8) |
|
|
(sequence () |
|
|
(set cbit (add-cflag w lit8 0)) |
|
|
(set dcbit (add-dcflag w lit8 0)) |
|
|
(set w (add w lit8)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni subw_l "SUB W,literal" |
|
|
() |
|
|
"sub W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_SUB_L lit8) |
|
|
(sequence () |
|
|
(set cbit (not (sub-cflag lit8 w 0))) |
|
|
(set dcbit (not (sub-dcflag lit8 w 0))) |
|
|
(set zbit (zflag (sub w lit8))) |
|
|
(set w (sub lit8 w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni cmpw_l "CMP W,literal" |
|
|
() |
|
|
"cmp W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_CMP_L lit8) |
|
|
(sequence () |
|
|
(set cbit (not (sub-cflag lit8 w 0))) |
|
|
(set dcbit (not (sub-dcflag lit8 w 0))) |
|
|
(set zbit (zflag (sub w lit8)))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni retw_l "RETW literal" |
|
|
() |
|
|
"retw #$lit8" |
|
|
(+ OP4_LITERAL OP4MID_RETW_L lit8) |
|
|
(sequence ((USI new_pc)) |
|
|
(set w lit8) |
|
|
(set new_pc (c-call UHI "pop_pc_stack")) |
|
|
(set pabits (srl new_pc 13)) |
|
|
(set pc new_pc)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni csew_l "CSE W,literal" |
|
|
() |
|
|
"cse W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_CSE_L lit8) |
|
|
(if (eq w lit8) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni csnew_l "CSNE W,literal" |
|
|
() |
|
|
"csne W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_CSNE_L lit8) |
|
|
(if (not (eq w lit8)) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni push_l "Push #lit8" |
|
|
() |
|
|
"push #$lit8" |
|
|
(+ OP4_LITERAL OP4MID_PUSH_L lit8) |
|
|
(sequence () |
|
|
(c-call "push" lit8) |
|
|
(c-call VOID "adjuststackptr" (const -1)) |
|
|
|
|
|
) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni mulsw_l "Multiply W,literal (signed)" |
|
|
() |
|
|
"muls W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_MULS_L lit8) |
|
|
(sequence ((SI tmp)) |
|
|
(set tmp (mul (ext SI w) (ext SI (and UQI #xff lit8)))) |
|
|
(set w (and tmp #xFF)) |
|
|
(set mulh (srl tmp 8))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni muluw_l "Multiply W,literal (unsigned)" |
|
|
() |
|
|
"mulu W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_MULU_L lit8) |
|
|
(sequence ((USI tmp)) |
|
|
(set tmp (and #xFFFF (mul (zext USI w) (zext USI lit8)))) |
|
|
(set w (and tmp #xFF)) |
|
|
(set mulh (srl tmp 8))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni loadl_l "LoadL literal" |
|
|
(EXT-SKIP-INSN) |
|
|
"loadl #$lit8" |
|
|
(+ OP4_LITERAL OP4MID_LOADL_L lit8) |
|
|
(set dpl (and lit8 #x00FF)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni loadh_l "LoadH literal" |
|
|
(EXT-SKIP-INSN) |
|
|
"loadh #$lit8" |
|
|
(+ OP4_LITERAL OP4MID_LOADH_L lit8) |
|
|
(set dph (and lit8 #x00FF)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni loadl_a "LoadL addr16l" |
|
|
(EXT-SKIP-INSN) |
|
|
"loadl $addr16l" |
|
|
(+ OP4_LITERAL OP4MID_LOADL_L addr16l) |
|
|
(set dpl (and addr16l #x00FF)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni loadh_a "LoadH addr16h" |
|
|
(EXT-SKIP-INSN) |
|
|
"loadh $addr16h" |
|
|
(+ OP4_LITERAL OP4MID_LOADH_L addr16h) |
|
|
(set dph (and addr16l #x0FF00)) |
|
|
() |
|
|
) |
|
|
|
|
|
;; THIS NO LONGER EXISTS -> Now LOADL |
|
|
;;(dni bank_l "Bank literal" |
|
|
;; () |
|
|
;; "bank #$lit8" |
|
|
;; (+ OP4_LITERAL OP4MID_BANK_L lit8) |
|
|
;; (set bank lit8) |
|
|
;; () |
|
|
;;) |
|
|
|
|
|
(dni addcfr_w "Add w/carry fr,W" |
|
|
() |
|
|
"addc $fr,W" |
|
|
(+ OP6_ADDC DIR_NOTTO_W fr) |
|
|
(sequence ((QI result) (BI newcbit) (QI isLreg) (HI 16bval)) |
|
|
(set newcbit (add-cflag w fr cbit)) |
|
|
(set dcbit (add-dcflag w fr cbit)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
(set 16bval (addc HI 16bval w cbit)) |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set result (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
(set result (addc w fr cbit)) ;; else part |
|
|
) |
|
|
|
|
|
(set zbit (zflag result)) |
|
|
(set cbit newcbit) |
|
|
(set fr result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni addcw_fr "Add w/carry W,fr" |
|
|
() |
|
|
"addc W,$fr" |
|
|
(+ OP6_ADDC DIR_TO_W fr) |
|
|
(sequence ((QI result) (BI newcbit)) |
|
|
(set newcbit (add-cflag w fr cbit)) |
|
|
(set dcbit (add-dcflag w fr cbit)) |
|
|
(set result (addc w fr cbit)) |
|
|
(set zbit (zflag result)) |
|
|
(set cbit newcbit) |
|
|
(set w result)) |
|
|
() |
|
|
) |
|
|
|
|
|
|
|
|
(dni incsnz_fr "Skip if fr++ not zero" |
|
|
() |
|
|
"incsnz $fr" |
|
|
(+ OP6_INCSNZ DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; Do 16 bit arithmetic. |
|
|
(set 16bval (add HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
(set fr (add fr 1)) ; Do 8 bit arithmetic. |
|
|
) |
|
|
(if (not (zflag fr)) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni incsnzw_fr "Skip if W=fr+1 not zero" |
|
|
() |
|
|
"incsnz W,$fr" |
|
|
(+ OP6_INCSNZ DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (add fr 1)) |
|
|
(if (not (zflag w)) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni mulsw_fr "Multiply W,fr (signed)" |
|
|
() |
|
|
"muls W,$fr" |
|
|
(+ OP6_MULS DIR_TO_W fr) |
|
|
(sequence ((SI tmp)) |
|
|
(set tmp (mul (ext SI w) (ext SI fr))) |
|
|
(set w (and tmp #xFF)) |
|
|
(set mulh (srl tmp 8))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni muluw_fr "Multiply W,fr (unsigned)" |
|
|
() |
|
|
"mulu W,$fr" |
|
|
(+ OP6_MULU DIR_TO_W fr) |
|
|
(sequence ((USI tmp)) |
|
|
(set tmp (and #xFFFF (mul (zext USI w) (zext USI fr)))) |
|
|
(set w (and tmp #xFF)) |
|
|
(set mulh (srl tmp 8))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni decsnz_fr "Skip if fr-- not zero" |
|
|
() |
|
|
"decsnz $fr" |
|
|
(+ OP6_DECSNZ DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (sub HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set fr (sub fr 1)) |
|
|
) |
|
|
(if (not (zflag fr)) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni decsnzw_fr "Skip if W=fr-1 not zero" |
|
|
() |
|
|
"decsnz W,$fr" |
|
|
(+ OP6_DECSNZ DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (sub fr 1)) |
|
|
(if (not (zflag w)) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni subcw_fr "Subract w/carry W,fr" |
|
|
() |
|
|
"subc W,$fr" |
|
|
(+ OP6_SUBC DIR_TO_W fr) |
|
|
(sequence ((QI result) (BI newcbit)) |
|
|
(set newcbit (not (sub-cflag fr w (not cbit)))) |
|
|
(set dcbit (not (sub-dcflag fr w (not cbit)))) |
|
|
(set result (subc fr w (not cbit))) |
|
|
(set zbit (zflag result)) |
|
|
(set cbit newcbit) |
|
|
(set w result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni subcfr_w "Subtract w/carry fr,W" |
|
|
() |
|
|
"subc $fr,W" |
|
|
(+ OP6_SUBC DIR_NOTTO_W fr) |
|
|
(sequence ((QI result) (BI newcbit) (QI isLreg) (HI 16bval)) |
|
|
(set newcbit (not (sub-cflag fr w (not cbit)))) |
|
|
(set dcbit (not (sub-dcflag fr w (not cbit)))) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (subc HI 16bval w (not cbit))) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set result (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set result (subc fr w (not cbit))) |
|
|
) |
|
|
|
|
|
|
|
|
(set zbit (zflag result)) |
|
|
(set cbit newcbit) |
|
|
(set fr result)) |
|
|
() |
|
|
) |
|
|
|
|
|
|
|
|
(dni pop_fr "Pop fr" |
|
|
() |
|
|
"pop $fr" |
|
|
(+ OP6_POP (f-dir 1) fr) |
|
|
(sequence() |
|
|
(set fr (c-call QI "pop")) |
|
|
(c-call VOID "adjuststackptr" (const 1)) |
|
|
) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni push_fr "Push fr" |
|
|
() |
|
|
"push $fr" |
|
|
(+ OP6_POP (f-dir 0) fr) |
|
|
(sequence() |
|
|
(c-call "push" fr) |
|
|
(c-call VOID "adjuststackptr" (const -1)) |
|
|
) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni csew_fr "Skip if equal W,fr" |
|
|
() |
|
|
"cse W,$fr" |
|
|
(+ OP6_CSE (f-dir 1) fr) |
|
|
(if (eq w fr) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni csnew_fr "Skip if not-equal W,fr" |
|
|
() |
|
|
"csne W,$fr" |
|
|
(+ OP6_CSE (f-dir 0) fr) |
|
|
(if (not (eq w fr)) |
|
|
(skip 1)) |
|
|
() |
|
|
) |
|
|
|
|
|
;;(dni csaw_fr "Skip if W above fr" |
|
|
;; ((MACH ip2022ext)) |
|
|
;; "csa W,$fr" |
|
|
;; (+ OP6_CSAB (f-dir 1) fr) |
|
|
;; (if (gt w fr) |
|
|
;; (skip 1)) |
|
|
;; () |
|
|
;;) |
|
|
|
|
|
;;(dni csbw_fr "Skip if W below fr" |
|
|
;; ((MACH ip2022ext)) |
|
|
;; "csb W,$fr" |
|
|
;; (+ OP6_CSAB (f-dir 0) fr) |
|
|
;; (if (lt w fr) |
|
|
;; (skip 1)) |
|
|
;; () |
|
|
;;) |
|
|
|
|
|
(dni incsz_fr "Skip if fr++ zero" |
|
|
() |
|
|
"incsz $fr" |
|
|
(+ OP6_INCSZ DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (add HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set fr (add fr 1)) |
|
|
) |
|
|
(if (zflag fr) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni incszw_fr "Skip if W=fr+1 zero" |
|
|
() |
|
|
"incsz W,$fr" |
|
|
(+ OP6_INCSZ DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (add fr 1)) |
|
|
(if (zflag w) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni swap_fr "Swap fr nibbles" |
|
|
() |
|
|
"swap $fr" |
|
|
(+ OP6_SWAP DIR_NOTTO_W fr) |
|
|
(set fr (or (and (sll fr 4) #xf0) |
|
|
(and (srl fr 4) #x0f))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni swapw_fr "Swap fr nibbles into W" |
|
|
() |
|
|
"swap W,$fr" |
|
|
(+ OP6_SWAP DIR_TO_W fr) |
|
|
(set w (or (and (sll fr 4) #xf0) |
|
|
(and (srl fr 4) #x0f))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni rl_fr "Rotate fr left with carry" |
|
|
() |
|
|
"rl $fr" |
|
|
(+ OP6_RL DIR_NOTTO_W fr) |
|
|
(sequence ((QI newfr) (BI newc)) |
|
|
(set newc (and fr #x80)) |
|
|
(set newfr (or (sll fr 1) (if QI cbit 1 0))) |
|
|
(set cbit (if QI newc 1 0)) |
|
|
(set fr newfr)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni rlw_fr "Rotate fr left with carry into W" |
|
|
() |
|
|
"rl W,$fr" |
|
|
(+ OP6_RL DIR_TO_W fr) |
|
|
(sequence ((QI newfr) (BI newc)) |
|
|
(set newc (and fr #x80)) |
|
|
(set newfr (or (sll fr 1) (if QI cbit 1 0))) |
|
|
(set cbit (if QI newc 1 0)) |
|
|
(set w newfr)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni rr_fr "Rotate fr right with carry" |
|
|
() |
|
|
"rr $fr" |
|
|
(+ OP6_RR DIR_NOTTO_W fr) |
|
|
(sequence ((QI newfr) (BI newc)) |
|
|
(set newc (and fr #x01)) |
|
|
(set newfr (or (srl fr 1) (if QI cbit #x80 #x00))) |
|
|
(set cbit (if QI newc 1 0)) |
|
|
(set fr newfr)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni rrw_fr "Rotate fr right with carry into W" |
|
|
() |
|
|
"rr W,$fr" |
|
|
(+ OP6_RR DIR_TO_W fr) |
|
|
(sequence ((QI newfr) (BI newc)) |
|
|
(set newc (and fr #x01)) |
|
|
(set newfr (or (srl fr 1) (if QI cbit #x80 #x00))) |
|
|
(set cbit (if QI newc 1 0)) |
|
|
(set w newfr)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni decsz_fr "Skip if fr-- zero" |
|
|
() |
|
|
"decsz $fr" |
|
|
(+ OP6_DECSZ DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (sub HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set fr (sub fr 1)) |
|
|
) |
|
|
(if (zflag fr) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni decszw_fr "Skip if W=fr-1 zero" |
|
|
() |
|
|
"decsz W,$fr" |
|
|
(+ OP6_DECSZ DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (sub fr 1)) |
|
|
(if (zflag w) |
|
|
(skip 1))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni inc_fr "Increment fr" |
|
|
() |
|
|
"inc $fr" |
|
|
(+ OP6_INC DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (add HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set fr (add fr 1)) |
|
|
) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni incw_fr "Increment fr into w" |
|
|
() |
|
|
"inc W,$fr" |
|
|
(+ OP6_INC DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (add fr 1)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni not_fr "Invert fr" |
|
|
() |
|
|
"not $fr" |
|
|
(+ OP6_NOT DIR_NOTTO_W fr) |
|
|
(sequence () |
|
|
(set fr (inv fr)) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni notw_fr "Invert fr into w" |
|
|
() |
|
|
"not W,$fr" |
|
|
(+ OP6_NOT DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (inv fr)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni test_fr "Test fr" |
|
|
() |
|
|
"test $fr" |
|
|
(+ OP6_TEST DIR_NOTTO_W fr) |
|
|
(sequence () |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni movw_l "MOV W,literal" |
|
|
() |
|
|
"mov W,#$lit8" |
|
|
(+ OP4_LITERAL OP4MID_MOV_L lit8) |
|
|
(set w lit8) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni movfr_w "Move/test w into fr" |
|
|
() |
|
|
"mov $fr,W" |
|
|
(+ OP6_OTHER1 DIR_NOTTO_W fr) |
|
|
(set fr w) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni movw_fr "Move/test fr into w" |
|
|
() |
|
|
"mov W,$fr" |
|
|
(+ OP6_TEST DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w fr) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
|
|
|
(dni addfr_w "Add fr,W" |
|
|
() |
|
|
"add $fr,W" |
|
|
(+ OP6_ADD DIR_NOTTO_W fr) |
|
|
(sequence ((QI result) (QI isLreg) (HI 16bval)) |
|
|
(set cbit (add-cflag w fr 0)) |
|
|
(set dcbit (add-dcflag w fr 0)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
|
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
(set 16bval (add HI (and w #xFF) 16bval)) |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set result (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
(set result (addc w fr 0)) ;; else part |
|
|
) |
|
|
(set zbit (zflag result)) |
|
|
(set fr result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni addw_fr "Add W,fr" |
|
|
() |
|
|
"add W,$fr" |
|
|
(+ OP6_ADD DIR_TO_W fr) |
|
|
(sequence ((QI result)) |
|
|
(set cbit (add-cflag w fr 0)) |
|
|
(set dcbit (add-dcflag w fr 0)) |
|
|
(set result (addc w fr 0)) |
|
|
(set zbit (zflag result)) |
|
|
(set w result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni xorfr_w "XOR fr,W" |
|
|
() |
|
|
"xor $fr,W" |
|
|
(+ OP6_XOR DIR_NOTTO_W fr) |
|
|
(sequence () |
|
|
(set fr (xor w fr)) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni xorw_fr "XOR W,fr" |
|
|
() |
|
|
"xor W,$fr" |
|
|
(+ OP6_XOR DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (xor fr w)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni andfr_w "AND fr,W" |
|
|
() |
|
|
"and $fr,W" |
|
|
(+ OP6_AND DIR_NOTTO_W fr) |
|
|
(sequence () |
|
|
(set fr (and w fr)) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni andw_fr "AND W,fr" |
|
|
() |
|
|
"and W,$fr" |
|
|
(+ OP6_AND DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (and fr w)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni orfr_w "OR fr,W" |
|
|
() |
|
|
"or $fr,W" |
|
|
(+ OP6_OR DIR_NOTTO_W fr) |
|
|
(sequence () |
|
|
(set fr (or w fr)) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni orw_fr "OR W,fr" |
|
|
() |
|
|
"or W,$fr" |
|
|
(+ OP6_OR DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (or fr w)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni dec_fr "Decrement fr" |
|
|
() |
|
|
"dec $fr" |
|
|
(+ OP6_DEC DIR_NOTTO_W fr) |
|
|
(sequence ((QI isLreg) (HI 16bval)) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (sub HI 16bval 1)) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set fr (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set fr (sub fr 1)) |
|
|
) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni decw_fr "Decrement fr into w" |
|
|
() |
|
|
"dec W,$fr" |
|
|
(+ OP6_DEC DIR_TO_W fr) |
|
|
(sequence () |
|
|
(set w (sub fr 1)) |
|
|
(set zbit (zflag w))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni subfr_w "Sub fr,W" |
|
|
() |
|
|
"sub $fr,W" |
|
|
(+ OP6_SUB DIR_NOTTO_W fr) |
|
|
(sequence ((QI result) (QI isLreg) (HI 16bval)) |
|
|
(set cbit (not (sub-cflag fr w 0))) |
|
|
(set dcbit (not (sub-dcflag fr w 0))) |
|
|
(LregCheck isLreg (ifield f-reg)) |
|
|
;; If fr is an Lreg, then we have to do 16-bit arithmetic. |
|
|
;; We can take advantage of the fact that by a lucky |
|
|
;; coincidence, the address of register xxxH is always |
|
|
;; one lower than the address of register xxxL. |
|
|
(if (eq isLreg #x1) |
|
|
(sequence() |
|
|
; Create the 16 bit value |
|
|
(set 16bval (reg h-spr (sub (ifield f-reg) 1))) |
|
|
(set 16bval (sll 16bval 8)) |
|
|
(set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) |
|
|
; New 16 bit instruction |
|
|
(set 16bval (sub HI 16bval (and w #xFF))) |
|
|
; Separate the 16 bit values into the H and L regs |
|
|
(set (reg h-spr (ifield f-reg)) (and 16bval #xFF)) |
|
|
(set (reg h-spr (sub (ifield f-reg) 1)) |
|
|
(and (srl 16bval 8) #xFF)) |
|
|
(set result (reg h-spr (ifield f-reg))) |
|
|
) |
|
|
; Original instruction |
|
|
(set result (subc fr w 0)) |
|
|
) |
|
|
(set zbit (zflag result)) |
|
|
(set fr result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni subw_fr "Sub W,fr" |
|
|
() |
|
|
"sub W,$fr" |
|
|
(+ OP6_SUB DIR_TO_W fr) |
|
|
(sequence ((QI result)) |
|
|
(set cbit (not (sub-cflag fr w 0))) |
|
|
(set dcbit (not (sub-dcflag fr w 0))) |
|
|
(set result (subc fr w 0)) |
|
|
(set zbit (zflag result)) |
|
|
(set w result)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni clr_fr "Clear fr" |
|
|
() |
|
|
"clr $fr" |
|
|
(+ OP6_OTHER2 (f-dir 1) fr) |
|
|
(sequence () |
|
|
(set fr 0) |
|
|
(set zbit (zflag fr))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni cmpw_fr "CMP W,fr" |
|
|
() |
|
|
"cmp W,$fr" |
|
|
(+ OP6_OTHER2 (f-dir 0) fr) |
|
|
(sequence () |
|
|
(set cbit (not (sub-cflag fr w 0))) |
|
|
(set dcbit (not (sub-dcflag fr w 0))) |
|
|
(set zbit (zflag (sub w fr)))) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni speed "Set speed" |
|
|
() |
|
|
"speed #$lit8" |
|
|
(+ (f-op8 1) lit8) |
|
|
(set (reg h-registers #x0E) lit8) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni ireadi "Insn memory read with increment" |
|
|
() |
|
|
"ireadi" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x1D)) |
|
|
(c-call "do_insn_read") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni iwritei "Insn memory write with increment" |
|
|
() |
|
|
"iwritei" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x1C)) |
|
|
(c-call "do_insn_write") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni fread "Flash read" |
|
|
() |
|
|
"fread" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x1B)) |
|
|
(c-call "do_flash_read") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni fwrite "Flash write" |
|
|
() |
|
|
"fwrite" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x1A)) |
|
|
(c-call "do_flash_write") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni iread "Insn memory read" |
|
|
() |
|
|
"iread" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x19)) |
|
|
(c-call "do_insn_read") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni iwrite "Insn memory write" |
|
|
() |
|
|
"iwrite" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x18)) |
|
|
(c-call "do_insn_write") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni page "Set insn page" |
|
|
(EXT-SKIP-INSN) |
|
|
;"page $page3" |
|
|
"page $addr16p" |
|
|
;(+ OP6_OTHER1 (f-op6-7low #x2) page3) |
|
|
;(set pabits (srl page3 13)) |
|
|
(+ OP6_OTHER1 (f-op6-7low #x2) addr16p) |
|
|
(set pabits addr16p) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni system "System call" |
|
|
() |
|
|
"system" |
|
|
(+ OP6_OTHER1 (f-op6-10low #xff)) |
|
|
(c-call "do_system") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni reti "Return from interrupt" |
|
|
() |
|
|
"reti #$reti3" |
|
|
(+ OP6_OTHER1 (f-op6-7low #x1) reti3) |
|
|
(c-call "do_reti" reti3) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni ret "Return" |
|
|
() |
|
|
"ret" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x07)) |
|
|
(sequence ((USI new_pc)) |
|
|
(set new_pc (c-call UHI "pop_pc_stack")) |
|
|
(set pabits (srl new_pc 13)) |
|
|
(set pc new_pc)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni int "Software interrupt" |
|
|
() |
|
|
"int" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x6)) |
|
|
(nop) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni breakx "Breakpoint with extended skip" |
|
|
(EXT-SKIP-INSN) |
|
|
"breakx" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x5)) |
|
|
(c-call "do_break" pc) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni cwdt "Clear watchdog timer" |
|
|
() |
|
|
"cwdt" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x4)) |
|
|
(c-call "do_clear_wdt") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni ferase "Flash erase" |
|
|
() |
|
|
"ferase" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x3)) |
|
|
(c-call "do_flash_erase") |
|
|
() |
|
|
) |
|
|
|
|
|
(dni retnp "Return, no page" |
|
|
() |
|
|
"retnp" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x2)) |
|
|
(sequence ((USI new_pc)) |
|
|
(set new_pc (c-call UHI "pop_pc_stack")) |
|
|
(set pc new_pc)) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni break "Breakpoint" |
|
|
() |
|
|
"break" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x1)) |
|
|
(c-call "do_break" pc) |
|
|
() |
|
|
) |
|
|
|
|
|
(dni nop "No operation" |
|
|
() |
|
|
"nop" |
|
|
(+ OP6_OTHER1 (f-op6-10low #x0)) |
|
|
(nop) |
|
|
() |
|
|
) |
|
|
|
|
|
|
|
|
; Macro instructions |
|
|
(dnmi sc "Skip on carry" |
|
|
() |
|
|
"sc" |
|
|
(emit sb (bitno 0) (fr #xB)) ; sb status.0 |
|
|
) |
|
|
|
|
|
(dnmi snc "Skip on no carry" |
|
|
() |
|
|
"snc" |
|
|
(emit snb (bitno 0) (fr #xB)) ; snb status.0 |
|
|
) |
|
|
|
|
|
(dnmi sz "Skip on zero" |
|
|
() |
|
|
"sz" |
|
|
(emit sb (bitno 2) (fr #xB)) ; sb status.2 |
|
|
) |
|
|
|
|
|
(dnmi snz "Skip on no zero" |
|
|
() |
|
|
"snz" |
|
|
(emit snb (bitno 2) (fr #xB)) ; snb status.2 |
|
|
) |
|
|
|
|
|
(dnmi skip "Skip always" |
|
|
(SKIPA) |
|
|
"skip" |
|
|
(emit snb (bitno 0) (fr 9)) ; snb pcl.0 | (pcl&1)<<12 |
|
|
) |
|
|
|
|
|
(dnmi skipb "Skip always" |
|
|
(SKIPA) |
|
|
"skip" |
|
|
(emit sb (bitno 0) (fr 9)) ; sb pcl.0 | (pcl&1)<<12 |
|
|
) |
|
|
|
|
|
|