URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [ip2k.cpu] - Rev 161
Compare with Previous | Blame | View Log
; 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 ADDTEST NOT INC DECSZ RR RL SWAP INCSZCSE 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(- - - - - - - LITERALCLRB 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_LRETW_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)
