* elf32-spu.c (build_stub): Fix malloc under-allocation.
[binutils.git] / cpu / ip2k.cpu
blobf329eab47d1719e7cd10f03b37d4d1bb185b7129
1 ; Ubicom IP2K CPU description.  -*- Scheme -*-
2 ; Copyright (C) 2002, 2009, 2011 Free Software Foundation, Inc.
4 ; Contributed by Red Hat Inc;
6 ; This file is part of the GNU Binutils.
8 ; This program is free software; you can redistribute it and/or modify
9 ; it under the terms of the GNU General Public License as published by
10 ; the Free Software Foundation; either version 3 of the License, or
11 ; (at your option) any later version.
13 ; This program is distributed in the hope that it will be useful,
14 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ; GNU General Public License for more details.
18 ; You should have received a copy of the GNU General Public License
19 ; along with this program; if not, write to the Free Software
20 ; Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 ; MA 02110-1301, USA.
23 (define-rtl-version 0 8)
25 (include "simplify.inc")
27 ; define-arch must appear first
29 (define-arch
30   (name ip2k) ; name of cpu family
31   (comment "Ubicom IP2000 family")
32   (default-alignment aligned)
33   (insn-lsb0? #t)
34   (machs ip2022 ip2022ext)
35   (isas ip2k)
38 ; Attributes.
40 (define-attr
41   (for insn)
42   (type boolean)
43   (name EXT-SKIP-INSN)
44   (comment "instruction is a PAGE, LOADL, LOADH or BREAKX instruction")
47 (define-attr
48   (for insn)
49   (type boolean)
50   (name SKIPA)
51   (comment "instruction is a SKIP instruction")
54 ; Instruction set parameters.
56 (define-isa
57   (name ip2k)
58   (comment "Ubicom IP2000 ISA")
60   (default-insn-word-bitsize 16)
61   (default-insn-bitsize 16)
62   (base-insn-bitsize 16)
65 ; Cpu family definitions.
68 (define-cpu
69   ; cpu names must be distinct from the architecture name and machine names.
70   (name ip2kbf)
71   (comment "Ubicom IP2000 Family")
72   (endian big)
73   (word-bitsize 16)
76 (define-mach
77   (name ip2022)
78   (comment "Ubicom IP2022")
79   (cpu ip2kbf)
82 (define-mach
83   (name ip2022ext)
84   (comment "Ubicom IP2022 extended")
85   (cpu ip2kbf)
89 ; Model descriptions.
91 (define-model
92   (name ip2k) (comment "VPE 2xxx") (attrs)
93   (mach ip2022ext)
95   (unit u-exec "Execution Unit" ()
96         1 1 ; issue done
97         () ; state
98         () ; inputs
99         () ; outputs
100         () ; profile action (default)
101         )
105 ; FIXME: It might simplify things to separate the execute process from the
106 ; one that updates the PC.
108 ; Instruction fields.
110 ; Attributes:
111 ; XXX: what VPE attrs
112 ; PCREL-ADDR: pc relative value (for reloc and disassembly purposes)
113 ; ABS-ADDR: absolute address (for reloc and disassembly purposes?)
114 ; RESERVED: bits are not used to decode insn, must be all 0
115 ; RELOC: there is a relocation associated with this field (experiment)
118 (dnf f-imm8      "imm8"                () 7 8)
119 (dnf f-reg       "reg"         (ABS-ADDR) 8 9)
120 (dnf f-addr16cjp "addr16cjp"   (ABS-ADDR) 12 13)
121 (dnf f-dir       "dir"                 () 9 1)
122 (dnf f-bitno     "bit number"          () 11 3)
123 (dnf f-op3       "op3"                 () 15 3)
124 (dnf f-op4       "op4"                 () 15 4)
125 (dnf f-op4mid    "op4mid"              () 11 4)
126 (dnf f-op6       "op6"                 () 15 6)
127 (dnf f-op8       "op8"                 () 15 8)
128 (dnf f-op6-10low "op6-10low"           () 9 10)
129 (dnf f-op6-7low  "op6-7low"            () 9 7)
130 (dnf f-reti3     "reti3"               () 2 3)
131 (dnf f-skipb     "sb/snb"      (ABS-ADDR) 12 1)
132 (dnf f-page3     "page3"               ()  2 3)
133 ;(define-ifield (name f-page3) (comment "page3") (attrs) (start 2) (length 3)
134 ;  (encode (value pc) (srl WI value 13))
135 ;  (decode (value pc) (sll WI value 13))
137 ; To fix the page/call asymmetry
138 ;(define-ifield (name f-page3) (comment "page3") (attrs) (start 2) (length 3)
139 ;  (encode (value pc) (srl WI value 13))
140 ;  (decode (value pc) (sll WI value 13))
145 ; Enums.
147 ; insn-op6: bits 15-10
148 (define-normal-insn-enum insn-op6 "op6 enums" () OP6_ f-op6
149   (OTHER1 OTHER2 SUB DEC OR AND XOR ADD 
150    TEST NOT INC DECSZ RR RL SWAP INCSZ
151    CSE POP SUBC DECSNZ MULU MULS INCSNZ  ADDC
152    - - - - - - - -   
153    - - - - - - - -
154    - - - - - - - -
155    - - - - - - - -
156    - - - - - - - -   
157    )
160 ; insn-dir: bit 9
161 (define-normal-insn-enum insn-dir "dir enums" () DIR_ f-dir
162   ; This bit specifies the polarity of many two-operand instructions:
163   ; TO_W writes result to W regiser  (eg. ADDC W,$fr)
164   ; NOTTO_W writes result in general register  (eg. ADDC $fr,W)
165   (TO_W NOTTO_W)
169 ; insn-op4: bits 15-12
170 (define-normal-insn-enum insn-op4 "op4 enums" () OP4_ f-op4
171   (- - - - - - - LITERAL
172    CLRB SETB SNB SB - - - -
173    )
176 ; insn-op4mid: bits 11-8
177 ; used for f-op4=LITERAL
178 (define-normal-insn-enum insn-op4mid "op4mid enums" () OP4MID_ f-op4mid
179   (LOADH_L LOADL_L MULU_L MULS_L PUSH_L  -  CSNE_L CSE_L
180    RETW_L CMP_L SUB_L ADD_L MOV_L OR_L AND_L XOR_L)
183 ; insn-op3: bits 15-13
184 (define-normal-insn-enum insn-op3 "op3 enums" () OP3_ f-op3
185   (- - - - - - CALL JMP)
189   
190 ; Hardware pieces.
192 ; Bank-relative general purpose registers
194 ; (define-pmacro (build-reg-name n) (.splice (.str "$" n) n))
196 (define-keyword
197   (name register-names)
198   (enum-prefix H-REGISTERS-)
199   (values
200    ; These are the "Special Purpose Registers" that are not reserved
201    ("ADDRSEL" #x2) ("ADDRX" #x3)
202    ("IPH" #x4) ("IPL" #x5) ("SPH" #x6) ("SPL" #x7)
203    ("PCH" #x8) ("PCL" #x9) ("WREG" #xA) ("STATUS" #xB)
204    ("DPH" #xC) ("DPL" #xD) ("SPDREG" #xE) ("MULH" #xF)
205    ("ADDRH" #x10) ("ADDRL" #x11) ("DATAH" #x12) ("DATAL" #x13)
206    ("INTVECH" #x14) ("INTVECL" #x15) ("INTSPD" #x16) ("INTF" #x17)
207    ("INTE" #x18) ("INTED" #x19) ("FCFG" #x1A) ("TCTRL" #x1B)
208    ("XCFG" #x1C) ("EMCFG" #x1D) ("IPCH" #x1E) ("IPCL" #x1F)
209    ("RAIN" #x20) ("RAOUT" #x21) ("RADIR" #x22) ("LFSRH" #x23)
210    ("RBIN" #x24) ("RBOUT" #x25) ("RBDIR" #x26) ("LFSRL" #x27)
211    ("RCIN" #x28) ("RCOUT" #x29) ("RCDIR" #x2A) ("LFSRA" #x2B)
212    ("RDIN" #x2C) ("RDOUT" #x2D) ("RDDIR" #x2E)   
213    ("REIN" #x30) ("REOUT" #x31) ("REDIR" #x32)   
214    ("RFIN" #x34) ("RFOUT" #x35) ("RFDIR" #x36)
215                  ("RGOUT" #x39) ("RGDIR" #x3A)
216    ("RTTMR" #x40) ("RTCFG" #x41) ("T0TMR" #x42) ("T0CFG" #x43)
217    ("T1CNTH" #x44) ("T1CNTL" #x45) ("T1CAP1H" #x46) ("T1CAP1L" #x47)
218    ("T1CAP2H" #x48) ("T1CMP2H" #x48) ("T1CAP2L" #x49) ("T1CMP2L" #x49) ; note aliases
219                                      ("T1CMP1H" #x4A) ("T1CMP1L" #x4B)
220    ("T1CFG1H" #x4C) ("T1CFG1L" #x4D) ("T1CFG2H" #x4E) ("T1CFG2L" #x4F)
221    ("ADCH" #x50) ("ADCL" #x51) ("ADCCFG" #x52) ("ADCTMR" #x53)
222    ("T2CNTH" #x54) ("T2CNTL" #x55) ("T2CAP1H" #x56) ("T2CAP1L" #x57)
223    ("T2CAP2H" #x58) ("T2CMP2H" #x58) ("T2CAP2L" #x59) ("T2CMP2L" #x59) ; note aliases
224                                      ("T2CMP1H" #x5A) ("T2CMP1L" #x5B)
225    ("T2CFG1H" #x5C) ("T2CFG1L" #x5D) ("T2CFG2H" #x5E) ("T2CFG2L" #x5F)
226    ("S1TMRH" #x60) ("S1TMRL" #x61) ("S1TBUFH" #x62) ("S1TBUFL" #x63)
227    ("S1TCFG" #x64) ("S1RCNT" #x65) ("S1RBUFH" #x66) ("S1RBUFL" #x67)
228    ("S1RCFG" #x68) ("S1RSYNC" #x69) ("S1INTF" #x6A) ("S1INTE" #x6B)
229    ("S1MODE" #x6C) ("S1SMASK" #x6D) ("PSPCFG" #x6E) ("CMPCFG" #x6F)
230    ("S2TMRH" #x70) ("S2TMRL" #x71) ("S2TBUFH" #x72) ("S2TBUFL" #x73)
231    ("S2TCFG" #x74) ("S2RCNT" #x75) ("S2RBUFH" #x76) ("S2RBUFL" #x77)
232    ("S2RCFG" #x78) ("S2RSYNC" #x79) ("S2INTF" #x7A) ("S2INTE" #x7B)
233    ("S2MODE" #x7C) ("S2SMASK" #x7D) ("CALLH" #x7E) ("CALLL" #x7F))
234   )
236 (define-hardware
237   (name h-spr)
238   (comment "special-purpose registers")
239   (type register QI (128))
240   (get (index) (c-call QI "get_spr" index ))
241   (set (index newval) (c-call VOID "set_spr" index newval ))
245 ;;(define-hardware
246 ;;  (name h-gpr-global)
247 ;;  (comment "gpr registers - global")
248 ;;  (type register QI (128))
251 ; The general register
253 (define-hardware
254   (name h-registers)
255   (comment "all addressable registers")
256   (attrs VIRTUAL)
257   (type register QI (512))
258   (get (index) (c-call QI "get_h_registers" index ))
259   (set (index newval) (c-call VOID "set_h_registers" index newval ))
262 ; The hardware stack.
263 ; Use {push,pop}_pc_stack c-calls to operate on this hardware element.
265 (define-hardware
266   (name h-stack)
267   (comment "hardware stack")
268   (type register UHI (16))
271 (dsh h-pabits "page bits" () (register QI))
272 (dsh h-zbit "zero bit" () (register BI))
273 (dsh h-cbit "carry bit" () (register BI))
274 (dsh h-dcbit "digit-carry bit" () (register BI))
275 (dnh h-pc "program counter" (PC PROFILE) (pc) () () ())
278 ; Operands
280 (define-operand (name addr16cjp) (comment "13-bit address") (attrs) 
281   (type h-uint) (index f-addr16cjp) (handlers (parse "addr16_cjp") (print "dollarhex_cj"))) ; overload lit8 printer
282 (define-operand (name fr) (comment "register") (attrs) 
283   (type h-registers) (index f-reg) (handlers (parse "fr") (print "fr")))
284 (define-operand (name lit8) (comment "8-bit signed literal") (attrs)
285   (type h-sint) (index f-imm8) (handlers (parse "lit8") (print "dollarhex8")))
286 (define-operand (name bitno) (comment "bit number") (attrs)
287   (type h-uint) (index f-bitno) (handlers (parse "bit3")(print "decimal")))
288 (define-operand (name addr16p) (comment "page number") (attrs)
289   (type h-uint) (index f-page3) (handlers (parse "addr16_cjp") (print "dollarhex_p")))
290 (define-operand (name addr16h) (comment "high 8 bits of address") (attrs)
291   (type h-uint) (index f-imm8) (handlers (parse "addr16") (print "dollarhex_addr16h")))
292 (define-operand (name addr16l) (comment "low 8 bits of address") (attrs)
293   (type h-uint) (index f-imm8) (handlers (parse "addr16") (print "dollarhex_addr16l")))
294 (define-operand (name reti3) (comment "reti flags") (attrs)
295   (type h-uint) (index f-reti3) (handlers (print "dollarhex")))
296 (dnop pabits   "page bits"                 () h-pabits f-nil)
297 (dnop zbit     "zero bit"                  () h-zbit f-nil)
298 (dnop cbit     "carry bit"                 () h-cbit f-nil)
299 (dnop dcbit    "digit carry bit"           () h-dcbit f-nil)
300 ;;(dnop bank     "bank register"             () h-bank-no f-nil)
302 (define-pmacro w     (reg h-spr #x0A))
303 (define-pmacro mulh  (reg h-spr #x0F))
304 (define-pmacro dph   (reg h-spr #x0C))
305 (define-pmacro dpl   (reg h-spr #x0D))
306 (define-pmacro sph   (reg h-spr #x06))
307 (define-pmacro spl   (reg h-spr #x07))
308 (define-pmacro iph   (reg h-spr #x04))
309 (define-pmacro ipl   (reg h-spr #x05))
310 (define-pmacro addrh (reg h-spr #x10))
311 (define-pmacro addrl (reg h-spr #x11))
315 ; Pseudo-RTL for DC flag calculations
316 ; "DC" = "digit carry", ie carry between nibbles
317 (define-pmacro (add-dcflag a b c)
318   (add-cflag (sll QI a 4) (sll QI b 4) c)
321 (define-pmacro (sub-dcflag a b c)
322   (sub-cflag (sll QI a 4) (sll QI b 4) c)
325 ; Check to see if an fr is one of IPL, SPL, DPL, ADDRL, PCL.
326 (define-pmacro (LregCheck isLreg fr9bit)
327    (sequence()
328       (set isLreg #x0) ;; Assume it's not an Lreg
329       (if (or (or (eq fr9bit #x5) (eq fr9bit #x7))
330               (or (eq fr9bit #x9)
331                   (or (eq fr9bit #xd) (eq fr9bit #x11))))
332           (set isLreg #x1)
333       )
334    )
338 ; Instructions, in order of the "Instruction Set Map" table on
339 ; pp 19-20 of IP2022 spec V1.09
341 (dni jmp "Jump"
342      ()
343      "jmp $addr16cjp"
344      (+ OP3_JMP addr16cjp)
345      (set pc (or (sll pabits 13) addr16cjp))
346      ()
349 ; note that in call, we push pc instead of pc + 1 because the ip2k increments
350 ; the pc prior to execution of the instruction
351 (dni call "Call"
352      ()
353      "call $addr16cjp"
354      (+ OP3_CALL addr16cjp)
355      (sequence ()
356                (c-call "push_pc_stack" pc)
357                (set pc (or (sll pabits 13) addr16cjp)))
358      ()
361 (dni sb "Skip if bit set"
362      ()
363      "sb $fr,$bitno"
364      (+ OP4_SB bitno fr)
365      (if (and fr (sll 1 bitno))
366          (skip 1))
367      ()
370 (dni snb "Skip if bit clear"
371      ()
372      "snb $fr,$bitno"
373      (+ OP4_SNB bitno fr)
374      (if (not (and fr (sll 1 bitno)))
375          (skip 1))
376      ()
379 (dni setb "Set bit"
380      ()
381      "setb $fr,$bitno"
382      (+ OP4_SETB bitno fr)
383      (set fr (or fr (sll 1 bitno)))
384      ()
387 (dni clrb "Clear bit"
388      ()
389      "clrb $fr,$bitno"
390      (+ OP4_CLRB bitno fr)
391      (set fr (and fr (inv (sll 1 bitno))))
392      ()
395 (dni xorw_l "XOR W,literal"
396      ()
397      "xor W,#$lit8"
398      (+ OP4_LITERAL OP4MID_XOR_L lit8)
399      (sequence ()
400                (set w (xor w lit8))
401                (set zbit (zflag w)))
402      ()
405 (dni andw_l "AND W,literal"
406      ()
407      "and W,#$lit8"
408      (+ OP4_LITERAL OP4MID_AND_L lit8)
409      (sequence ()
410                (set w (and w lit8))
411                (set zbit (zflag w)))
412      ()
415 (dni orw_l "OR W,literal"
416      ()
417      "or W,#$lit8"
418      (+ OP4_LITERAL OP4MID_OR_L lit8)
419      (sequence ()
420                (set w (or w lit8))
421                (set zbit (zflag w)))
422      ()
425 (dni addw_l "ADD W,literal"
426      ()
427      "add W,#$lit8"
428      (+ OP4_LITERAL OP4MID_ADD_L lit8)
429      (sequence ()
430                (set cbit (add-cflag w lit8 0))
431                (set dcbit (add-dcflag w lit8 0))
432                (set w (add w lit8))
433                (set zbit (zflag w)))
434      ()
437 (dni subw_l "SUB W,literal"
438      ()
439      "sub W,#$lit8"
440      (+ OP4_LITERAL OP4MID_SUB_L lit8)
441      (sequence ()
442                (set cbit (not (sub-cflag lit8 w 0)))
443                (set dcbit (not (sub-dcflag lit8 w 0)))
444                (set zbit (zflag (sub w lit8)))
445                (set w (sub lit8 w)))
446      ()
449 (dni cmpw_l "CMP W,literal"
450      ()
451      "cmp W,#$lit8"
452      (+ OP4_LITERAL OP4MID_CMP_L lit8)
453      (sequence ()
454                (set cbit (not (sub-cflag lit8 w 0)))
455                (set dcbit (not (sub-dcflag lit8 w 0)))
456                (set zbit (zflag (sub w lit8))))
457      ()
460 (dni retw_l "RETW literal"
461      ()
462      "retw #$lit8"
463      (+ OP4_LITERAL OP4MID_RETW_L lit8)
464      (sequence ((USI new_pc))
465                (set w lit8)
466                (set new_pc (c-call UHI "pop_pc_stack"))
467                (set pabits (srl new_pc 13))
468                (set pc new_pc))
469      ()
472 (dni csew_l "CSE W,literal"
473      ()
474      "cse W,#$lit8"
475      (+ OP4_LITERAL OP4MID_CSE_L lit8)
476      (if (eq w lit8)
477          (skip 1))
478      ()
481 (dni csnew_l "CSNE W,literal"
482      ()
483      "csne W,#$lit8"
484      (+ OP4_LITERAL OP4MID_CSNE_L lit8)
485      (if (not (eq w lit8))
486          (skip 1))
487      ()
490 (dni push_l "Push #lit8"
491      ()
492      "push #$lit8"
493      (+ OP4_LITERAL OP4MID_PUSH_L lit8)
494      (sequence ()
495         (c-call "push" lit8)
496         (c-call VOID "adjuststackptr" (const -1))
498      )
499      ()
502 (dni mulsw_l "Multiply W,literal (signed)"
503      ()
504      "muls W,#$lit8"
505      (+ OP4_LITERAL OP4MID_MULS_L lit8)
506      (sequence ((SI tmp))
507                (set tmp (mul (ext SI w) (ext SI (and UQI #xff lit8))))
508                (set w (and tmp #xFF))
509                (set mulh (srl tmp 8)))
510      ()
513 (dni muluw_l "Multiply W,literal (unsigned)"
514      ()
515      "mulu W,#$lit8"
516      (+ OP4_LITERAL OP4MID_MULU_L lit8)
517      (sequence ((USI tmp))
518                (set tmp (and #xFFFF (mul (zext USI w) (zext USI lit8))))
519                (set w (and tmp #xFF))
520                (set mulh (srl tmp 8)))
521      ()
524 (dni loadl_l "LoadL literal"
525     (EXT-SKIP-INSN)
526     "loadl #$lit8"
527     (+ OP4_LITERAL OP4MID_LOADL_L lit8)
528     (set dpl (and lit8 #x00FF))
529     ()
532 (dni loadh_l "LoadH literal"
533     (EXT-SKIP-INSN)
534     "loadh #$lit8"
535     (+ OP4_LITERAL OP4MID_LOADH_L lit8)
536     (set dph (and lit8 #x00FF))
537     ()
540 (dni loadl_a "LoadL addr16l"
541     (EXT-SKIP-INSN)
542     "loadl $addr16l"
543     (+ OP4_LITERAL OP4MID_LOADL_L addr16l)
544     (set dpl (and addr16l #x00FF))
545     ()
548 (dni loadh_a "LoadH addr16h"
549     (EXT-SKIP-INSN)
550     "loadh $addr16h"
551     (+ OP4_LITERAL OP4MID_LOADH_L addr16h)
552     (set dph (and addr16l #x0FF00))
553     ()
556 ;; THIS NO LONGER EXISTS -> Now LOADL
557 ;;(dni bank_l "Bank literal"
558 ;;     ()
559 ;;     "bank #$lit8"
560 ;;     (+ OP4_LITERAL OP4MID_BANK_L lit8)
561 ;;     (set bank lit8)
562 ;;     ()
565 (dni addcfr_w "Add w/carry fr,W"
566      ()
567      "addc $fr,W"
568      (+ OP6_ADDC DIR_NOTTO_W fr)
569      (sequence ((QI result) (BI newcbit) (QI isLreg) (HI 16bval))
570                (set newcbit (add-cflag w fr cbit))
571                (set dcbit (add-dcflag w fr cbit))
572                ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
573                ;; We can take advantage of the fact that by a lucky
574                ;; coincidence, the address of register xxxH is always      
575                ;; one lower than the address of register xxxL.
576                (LregCheck isLreg (ifield f-reg))
577                (if (eq isLreg #x1)
578                   (sequence() 
579                      (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
580                      (set 16bval (sll 16bval 8))
581                      (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF))) 
582                      (set 16bval (addc HI 16bval w cbit))
583                      (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
584                      (set (reg h-spr (sub (ifield f-reg) 1)) 
585                           (and (srl 16bval 8) #xFF))
586                      (set result (reg h-spr (ifield f-reg)))
587                   )      
588                (set result (addc w fr cbit)) ;; else part
589                )
591                (set zbit (zflag result))
592                (set cbit newcbit)
593                (set fr result))
594      ()
597 (dni addcw_fr "Add w/carry W,fr"
598      ()
599      "addc W,$fr"
600      (+ OP6_ADDC DIR_TO_W fr)
601      (sequence ((QI result) (BI newcbit))
602                (set newcbit (add-cflag w fr cbit))
603                (set dcbit (add-dcflag w fr cbit))
604                (set result (addc w fr cbit))
605                (set zbit (zflag result))
606                (set cbit newcbit)
607                (set w result))
608      ()
612 (dni incsnz_fr "Skip if fr++ not zero"
613      ()
614      "incsnz $fr"
615      (+ OP6_INCSNZ DIR_NOTTO_W fr)
616      (sequence ((QI isLreg) (HI 16bval))
617         (LregCheck isLreg (ifield f-reg))
618         ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
619         ;; We can take advantage of the fact that by a lucky
620         ;; coincidence, the address of register xxxH is always
621         ;; one lower than the address of register xxxL.
622         (if (eq isLreg #x1)
623            (sequence()
624               ; Create the 16 bit value
625               (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
626               (set 16bval (sll 16bval 8))
627               (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
628               ; Do 16 bit arithmetic.
629               (set 16bval (add HI 16bval 1))
630               ; Separate the 16 bit values into the H and L regs
631               (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
632               (set (reg h-spr (sub (ifield f-reg) 1))
633                    (and (srl 16bval 8) #xFF))
634               (set fr (reg h-spr (ifield f-reg)))
635            )
636            (set fr (add fr 1)) ; Do 8 bit arithmetic.
637         )
638         (if (not (zflag fr))
639            (skip 1)))
640      ()
643 (dni incsnzw_fr "Skip if W=fr+1  not zero"
644      ()
645      "incsnz W,$fr"
646      (+ OP6_INCSNZ DIR_TO_W fr)
647      (sequence ()
648                (set w (add fr 1))
649                (if (not (zflag w))
650                    (skip 1)))
651      ()
654 (dni mulsw_fr "Multiply W,fr (signed)"
655      ()
656      "muls W,$fr"
657      (+ OP6_MULS DIR_TO_W fr)
658      (sequence ((SI tmp))
659                (set tmp (mul (ext SI w) (ext SI fr)))
660                (set w (and tmp #xFF))
661                (set mulh (srl tmp 8)))
662      ()
665 (dni muluw_fr "Multiply W,fr (unsigned)"
666      ()
667      "mulu W,$fr"
668      (+ OP6_MULU DIR_TO_W fr)
669      (sequence ((USI tmp))
670                (set tmp (and #xFFFF (mul (zext USI w) (zext USI fr))))
671                (set w (and tmp #xFF))
672                (set mulh (srl tmp 8)))
673      ()
676 (dni decsnz_fr "Skip if fr-- not zero"
677      ()
678      "decsnz $fr"
679      (+ OP6_DECSNZ DIR_NOTTO_W fr)
680      (sequence ((QI isLreg) (HI 16bval))
681          (LregCheck isLreg (ifield f-reg))
682          ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
683          ;; We can take advantage of the fact that by a lucky
684          ;; coincidence, the address of register xxxH is always
685          ;; one lower than the address of register xxxL.
686          (if (eq isLreg #x1)
687             (sequence()
688                ; Create the 16 bit value
689                (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
690                (set 16bval (sll 16bval 8))
691                (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
692                ; New 16 bit instruction
693                (set 16bval (sub HI 16bval 1))
694                ; Separate the 16 bit values into the H and L regs
695                (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
696                (set (reg h-spr (sub (ifield f-reg) 1))
697                     (and (srl 16bval 8) #xFF))
698                (set fr (reg h-spr (ifield f-reg)))
699             )
700             ; Original instruction
701             (set fr (sub fr 1))
702          )
703             (if (not (zflag fr))
704                (skip 1)))
705      ()
708 (dni decsnzw_fr "Skip if W=fr-1 not zero"
709      ()
710      "decsnz W,$fr"
711      (+ OP6_DECSNZ DIR_TO_W fr)
712      (sequence ()
713                (set w (sub fr 1))
714                (if (not (zflag w))
715                    (skip 1)))
716      ()
719 (dni subcw_fr "Subract w/carry W,fr"
720      ()
721      "subc W,$fr"
722      (+ OP6_SUBC DIR_TO_W fr)
723      (sequence ((QI result) (BI newcbit))
724                (set newcbit (not (sub-cflag fr w (not cbit))))
725                (set dcbit (not (sub-dcflag fr w (not cbit))))
726                (set result (subc fr w (not cbit)))
727                (set zbit (zflag result))
728                (set cbit newcbit)
729                (set w result))
730      ()
733 (dni subcfr_w "Subtract w/carry fr,W"
734      ()
735      "subc $fr,W"
736      (+ OP6_SUBC DIR_NOTTO_W fr)
737      (sequence ((QI result) (BI newcbit) (QI isLreg) (HI 16bval))
738                (set newcbit (not (sub-cflag fr w (not cbit))))
739                (set dcbit (not (sub-dcflag fr w (not cbit))))
740                (LregCheck isLreg (ifield f-reg))
741                ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
742                ;; We can take advantage of the fact that by a lucky
743                ;; coincidence, the address of register xxxH is always
744                ;; one lower than the address of register xxxL.
745                (if (eq isLreg #x1)
746                   (sequence()
747                      ; Create the 16 bit value
748                      (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
749                      (set 16bval (sll 16bval 8))
750                      (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
751                      ; New 16 bit instruction
752                      (set 16bval (subc HI 16bval w (not cbit)))
753                      ; Separate the 16 bit values into the H and L regs
754                      (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
755                      (set (reg h-spr (sub (ifield f-reg) 1))
756                           (and (srl 16bval 8) #xFF))
757                      (set result (reg h-spr (ifield f-reg)))
758                   )
759                ; Original instruction
760                (set result (subc fr w (not cbit)))
761                )
764                (set zbit (zflag result))
765                (set cbit newcbit)
766                (set fr result))
767      ()
771 (dni pop_fr "Pop fr"
772      ()
773      "pop $fr"
774      (+ OP6_POP (f-dir 1) fr)
775      (sequence()
776         (set fr (c-call QI "pop")) 
777         (c-call VOID "adjuststackptr" (const 1))
778      )
779      ()
782 (dni push_fr "Push fr"
783      ()
784      "push $fr"
785      (+ OP6_POP (f-dir 0) fr)
786      (sequence()
787         (c-call "push" fr)
788         (c-call VOID "adjuststackptr" (const -1))
789      )
790      ()
793 (dni csew_fr "Skip if equal W,fr"
794      ()
795      "cse W,$fr"
796      (+ OP6_CSE (f-dir 1) fr)
797      (if (eq w fr)
798          (skip 1))
799      ()
802 (dni csnew_fr "Skip if not-equal W,fr"
803      ()
804      "csne W,$fr"
805      (+ OP6_CSE (f-dir 0) fr)
806      (if (not (eq w fr))
807          (skip 1))
808      ()
811 ;;(dni csaw_fr "Skip if W above fr"
812 ;;     ((MACH ip2022ext))
813 ;;     "csa W,$fr"
814 ;;     (+ OP6_CSAB (f-dir 1) fr)
815 ;;     (if (gt w fr)
816 ;;       (skip 1))
817 ;;    ()
820 ;;(dni csbw_fr "Skip if W below fr"
821 ;;     ((MACH ip2022ext))
822 ;;     "csb W,$fr"
823 ;;     (+ OP6_CSAB (f-dir 0) fr)
824 ;;     (if (lt w fr)
825 ;;       (skip 1))
826 ;;    ()
829 (dni incsz_fr "Skip if fr++ zero"
830      ()
831      "incsz $fr"
832      (+ OP6_INCSZ DIR_NOTTO_W fr)
833      (sequence ((QI isLreg) (HI 16bval))
834           (LregCheck isLreg (ifield f-reg))
835           ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
836           ;; We can take advantage of the fact that by a lucky
837           ;; coincidence, the address of register xxxH is always
838           ;; one lower than the address of register xxxL.
839           (if (eq isLreg #x1)
840              (sequence()
841                 ; Create the 16 bit value
842                 (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
843                 (set 16bval (sll 16bval 8))
844                 (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
845                 ; New 16 bit instruction
846                 (set 16bval (add HI 16bval 1))
847                 ; Separate the 16 bit values into the H and L regs
848                 (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
849                 (set (reg h-spr (sub (ifield f-reg) 1))
850                      (and (srl 16bval 8) #xFF))
851                 (set fr (reg h-spr (ifield f-reg)))
852              )
853              ; Original instruction
854              (set fr (add fr 1))
855           )
856                (if (zflag fr)
857                    (skip 1)))
858      ()
861 (dni incszw_fr "Skip if W=fr+1 zero"
862      ()
863      "incsz W,$fr"
864      (+ OP6_INCSZ DIR_TO_W fr)
865      (sequence ()
866                (set w (add fr 1))
867                (if (zflag w)
868                    (skip 1)))
869      ()
872 (dni swap_fr "Swap fr nibbles"
873      ()
874      "swap $fr"
875      (+ OP6_SWAP DIR_NOTTO_W fr)
876      (set fr (or (and (sll fr 4) #xf0)
877                  (and (srl fr 4) #x0f)))
878      ()
881 (dni swapw_fr "Swap fr nibbles into W"
882      ()
883      "swap W,$fr"
884      (+ OP6_SWAP DIR_TO_W fr)
885      (set w (or (and (sll fr 4) #xf0)
886                 (and (srl fr 4) #x0f)))
887      ()
890 (dni rl_fr "Rotate fr left with carry"
891      ()
892      "rl $fr"
893      (+ OP6_RL DIR_NOTTO_W fr)
894      (sequence ((QI newfr) (BI newc))
895                (set newc (and fr #x80))
896                (set newfr (or (sll fr 1) (if QI cbit 1 0)))
897                (set cbit (if QI newc 1 0))
898                (set fr newfr))
899      ()
902 (dni rlw_fr "Rotate fr left with carry into W"
903      ()
904      "rl W,$fr"
905      (+ OP6_RL DIR_TO_W fr)
906      (sequence ((QI newfr) (BI newc))
907                (set newc (and fr #x80))
908                (set newfr (or (sll fr 1) (if QI cbit 1 0)))
909                (set cbit (if QI newc 1 0))
910                (set w newfr))
911      ()
914 (dni rr_fr "Rotate fr right with carry"
915      ()
916      "rr $fr"
917      (+ OP6_RR DIR_NOTTO_W fr)
918      (sequence ((QI newfr) (BI newc))
919                (set newc (and fr #x01))
920                (set newfr (or (srl fr 1) (if QI cbit #x80 #x00)))
921                (set cbit (if QI newc 1 0))
922                (set fr newfr))
923      ()
926 (dni rrw_fr "Rotate fr right with carry into W"
927      ()
928      "rr W,$fr"
929      (+ OP6_RR DIR_TO_W fr)
930      (sequence ((QI newfr) (BI newc))
931                (set newc (and fr #x01))
932                (set newfr (or (srl fr 1) (if QI cbit #x80 #x00)))
933                (set cbit (if QI newc 1 0))
934                (set w newfr))
935      ()
938 (dni decsz_fr "Skip if fr-- zero"
939      ()
940      "decsz $fr"
941      (+ OP6_DECSZ DIR_NOTTO_W fr)
942      (sequence ((QI isLreg) (HI 16bval))
943           (LregCheck isLreg (ifield f-reg))
944           ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
945           ;; We can take advantage of the fact that by a lucky
946           ;; coincidence, the address of register xxxH is always
947           ;; one lower than the address of register xxxL.
948           (if (eq isLreg #x1)
949              (sequence()
950                 ; Create the 16 bit value
951                 (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
952                 (set 16bval (sll 16bval 8))
953                 (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
954                 ; New 16 bit instruction
955                 (set 16bval (sub HI 16bval 1))
956                 ; Separate the 16 bit values into the H and L regs
957                 (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
958                 (set (reg h-spr (sub (ifield f-reg) 1))
959                      (and (srl 16bval 8) #xFF))
960                 (set fr (reg h-spr (ifield f-reg)))
961              )
962              ; Original instruction
963              (set fr (sub fr 1))
964           )
965                (if (zflag fr)
966                    (skip 1)))
967      ()
970 (dni decszw_fr "Skip if W=fr-1 zero"
971      ()
972      "decsz W,$fr"
973      (+ OP6_DECSZ DIR_TO_W fr)
974      (sequence ()
975                (set w (sub fr 1))
976                (if (zflag w)
977                    (skip 1)))
978      ()
981 (dni inc_fr "Increment fr"
982      ()
983      "inc $fr"
984      (+ OP6_INC DIR_NOTTO_W fr)
985      (sequence ((QI isLreg) (HI 16bval))
986           (LregCheck isLreg (ifield f-reg))
987           ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
988           ;; We can take advantage of the fact that by a lucky
989           ;; coincidence, the address of register xxxH is always
990           ;; one lower than the address of register xxxL.
991           (if (eq isLreg #x1)
992              (sequence()
993                 ; Create the 16 bit value
994                 (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
995                 (set 16bval (sll 16bval 8))
996                 (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
997                 ; New 16 bit instruction
998                 (set 16bval (add HI 16bval 1))
999                 ; Separate the 16 bit values into the H and L regs
1000                 (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
1001                 (set (reg h-spr (sub (ifield f-reg) 1))
1002                      (and (srl 16bval 8) #xFF))
1003                 (set fr (reg h-spr (ifield f-reg)))
1004              )
1005              ; Original instruction
1006              (set fr (add fr 1))
1007            )
1008                (set zbit (zflag fr)))
1009      ()
1012 (dni incw_fr "Increment fr into w"
1013      ()
1014      "inc W,$fr"
1015      (+ OP6_INC DIR_TO_W fr)
1016      (sequence ()
1017                (set w (add fr 1))
1018                (set zbit (zflag w)))
1019      ()
1022 (dni not_fr "Invert fr"
1023      ()
1024      "not $fr"
1025      (+ OP6_NOT DIR_NOTTO_W fr)
1026      (sequence ()
1027                (set fr (inv fr))
1028                (set zbit (zflag fr)))
1029      ()
1032 (dni notw_fr "Invert fr into w"
1033      ()
1034      "not W,$fr"
1035      (+ OP6_NOT DIR_TO_W fr)
1036      (sequence ()
1037                (set w (inv fr))
1038                (set zbit (zflag w)))
1039      ()
1042 (dni test_fr "Test fr"
1043      ()
1044      "test $fr"
1045      (+ OP6_TEST DIR_NOTTO_W fr)
1046      (sequence ()
1047                (set zbit (zflag fr)))
1048      ()
1051 (dni movw_l "MOV W,literal"
1052      ()
1053      "mov W,#$lit8"
1054      (+ OP4_LITERAL OP4MID_MOV_L lit8)
1055      (set w lit8)
1056      ()
1059 (dni movfr_w "Move/test w into fr"
1060      ()
1061      "mov $fr,W"
1062      (+ OP6_OTHER1 DIR_NOTTO_W fr)
1063      (set fr w)
1064      ()
1067 (dni movw_fr "Move/test fr into w"
1068      ()
1069      "mov W,$fr"
1070      (+ OP6_TEST DIR_TO_W fr)
1071      (sequence ()
1072                (set w fr)
1073                (set zbit (zflag w)))
1074      ()
1078 (dni addfr_w "Add fr,W"
1079      ()
1080      "add $fr,W"
1081      (+ OP6_ADD DIR_NOTTO_W fr)
1082      (sequence ((QI result) (QI isLreg) (HI 16bval))
1083                (set cbit (add-cflag w fr 0))
1084                (set dcbit (add-dcflag w fr 0))
1085                (LregCheck isLreg (ifield f-reg))
1087                ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
1088                ;; We can take advantage of the fact that by a lucky
1089                ;; coincidence, the address of register xxxH is always 
1090                ;; one lower than the address of register xxxL.
1091                (if (eq isLreg #x1)
1092                   (sequence()
1093                      (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
1094                      (set 16bval (sll 16bval 8))
1095                      (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
1096                      (set 16bval (add HI (and w #xFF) 16bval))
1097                      (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
1098                      (set (reg h-spr (sub (ifield f-reg) 1))
1099                           (and (srl 16bval 8) #xFF))
1100                      (set result (reg h-spr (ifield f-reg)))
1101                   )
1102                (set result (addc w fr 0)) ;; else part
1103                )
1104                (set zbit (zflag result))
1105                (set fr result))
1106      ()
1109 (dni addw_fr "Add W,fr"
1110      ()
1111      "add W,$fr"
1112      (+ OP6_ADD DIR_TO_W fr)
1113      (sequence ((QI result))
1114                (set cbit (add-cflag w fr 0))
1115                (set dcbit (add-dcflag w fr 0))
1116                (set result (addc w fr 0))
1117                (set zbit (zflag result))
1118                (set w result))
1119      ()
1122 (dni xorfr_w "XOR fr,W"
1123      ()
1124      "xor $fr,W"
1125      (+ OP6_XOR DIR_NOTTO_W fr)
1126      (sequence ()
1127                (set fr (xor w fr))
1128                (set zbit (zflag fr)))
1129      ()
1132 (dni xorw_fr "XOR W,fr"
1133      ()
1134      "xor W,$fr"
1135      (+ OP6_XOR DIR_TO_W fr)
1136      (sequence ()
1137                (set w (xor fr w))
1138                (set zbit (zflag w)))
1139      ()
1142 (dni andfr_w "AND fr,W"
1143      ()
1144      "and $fr,W"
1145      (+ OP6_AND DIR_NOTTO_W fr)
1146      (sequence ()
1147                (set fr (and w fr))
1148                (set zbit (zflag fr)))
1149      ()
1152 (dni andw_fr "AND W,fr"
1153      ()
1154      "and W,$fr"
1155      (+ OP6_AND DIR_TO_W fr)
1156      (sequence ()
1157                (set w (and fr w))
1158                (set zbit (zflag w)))
1159      ()
1162 (dni orfr_w "OR fr,W"
1163      ()
1164      "or $fr,W"
1165      (+ OP6_OR DIR_NOTTO_W fr)
1166      (sequence ()
1167                (set fr (or w fr))
1168                (set zbit (zflag fr)))
1169      ()
1172 (dni orw_fr "OR W,fr"
1173      ()
1174      "or W,$fr"
1175      (+ OP6_OR DIR_TO_W fr)
1176      (sequence ()
1177                (set w (or fr w))
1178                (set zbit (zflag w)))
1179      ()
1182 (dni dec_fr "Decrement fr"
1183      ()
1184      "dec $fr"
1185      (+ OP6_DEC DIR_NOTTO_W fr)
1186      (sequence ((QI isLreg) (HI 16bval))
1187           (LregCheck isLreg (ifield f-reg))
1188           ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
1189           ;; We can take advantage of the fact that by a lucky
1190           ;; coincidence, the address of register xxxH is always
1191           ;; one lower than the address of register xxxL.
1192           (if (eq isLreg #x1)
1193              (sequence()
1194                 ; Create the 16 bit value
1195                 (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
1196                 (set 16bval (sll 16bval 8))
1197                 (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
1198                 ; New 16 bit instruction
1199                 (set 16bval (sub HI 16bval 1))
1200                 ; Separate the 16 bit values into the H and L regs
1201                 (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
1202                 (set (reg h-spr (sub (ifield f-reg) 1))
1203                      (and (srl 16bval 8) #xFF))
1204                 (set fr (reg h-spr (ifield f-reg)))
1205              )
1206              ; Original instruction
1207              (set fr (sub fr 1))
1208           )
1209              (set zbit (zflag fr)))
1210      ()
1213 (dni decw_fr "Decrement fr into w"
1214      ()
1215      "dec W,$fr"
1216      (+ OP6_DEC DIR_TO_W fr)
1217      (sequence ()
1218                (set w (sub fr 1))
1219                (set zbit (zflag w)))
1220      ()
1223 (dni subfr_w "Sub fr,W"
1224      ()
1225      "sub $fr,W"
1226      (+ OP6_SUB DIR_NOTTO_W fr)
1227      (sequence ((QI result) (QI isLreg) (HI 16bval))
1228                (set cbit (not (sub-cflag fr w 0)))
1229                (set dcbit (not (sub-dcflag fr w 0)))
1230                (LregCheck isLreg (ifield f-reg))
1231                ;; If fr is an Lreg, then we have to do 16-bit arithmetic.
1232                ;; We can take advantage of the fact that by a lucky
1233                ;; coincidence, the address of register xxxH is always
1234                ;; one lower than the address of register xxxL.
1235                (if (eq isLreg #x1)
1236                   (sequence()
1237                      ; Create the 16 bit value
1238                      (set 16bval (reg h-spr (sub (ifield f-reg) 1)))
1239                      (set 16bval (sll 16bval 8))
1240                      (set 16bval (or 16bval (and (reg h-spr (ifield f-reg)) #xFF)))
1241                      ; New 16 bit instruction
1242                      (set 16bval (sub HI 16bval (and w #xFF)))
1243                      ; Separate the 16 bit values into the H and L regs
1244                      (set (reg h-spr (ifield f-reg)) (and 16bval #xFF))
1245                      (set (reg h-spr (sub (ifield f-reg) 1))
1246                           (and (srl 16bval 8) #xFF))
1247                      (set result (reg h-spr (ifield f-reg)))
1248                   )
1249                ; Original instruction
1250                (set result (subc fr w 0))
1251                )
1252                (set zbit (zflag result))
1253                (set fr result))
1254      ()
1257 (dni subw_fr "Sub W,fr"
1258      ()
1259      "sub W,$fr"
1260      (+ OP6_SUB DIR_TO_W fr)
1261      (sequence ((QI result))
1262                (set cbit (not (sub-cflag fr w 0)))
1263                (set dcbit (not (sub-dcflag fr w 0)))
1264                (set result (subc fr w 0))
1265                (set zbit (zflag result))
1266                (set w result))
1267      ()
1270 (dni clr_fr "Clear fr"
1271      ()
1272      "clr $fr"
1273      (+ OP6_OTHER2 (f-dir 1) fr)
1274      (sequence ()
1275                (set fr 0)
1276                (set zbit (zflag fr)))
1277      ()
1280 (dni cmpw_fr "CMP W,fr"
1281      ()
1282      "cmp W,$fr"
1283      (+ OP6_OTHER2 (f-dir 0) fr)
1284      (sequence ()
1285                (set cbit (not (sub-cflag fr w 0)))
1286                (set dcbit (not (sub-dcflag fr w 0)))
1287                (set zbit (zflag (sub w fr))))
1288      ()
1291 (dni speed "Set speed"
1292      ()
1293      "speed #$lit8"
1294      (+ (f-op8 1) lit8)
1295      (set (reg h-registers #x0E) lit8)
1296      ()
1299 (dni ireadi "Insn memory read with increment"
1300      ()
1301      "ireadi"
1302      (+ OP6_OTHER1 (f-op6-10low #x1D))
1303      (c-call "do_insn_read")
1304      ()
1307 (dni iwritei "Insn memory write with increment"
1308      ()
1309      "iwritei"
1310      (+ OP6_OTHER1 (f-op6-10low #x1C))
1311      (c-call "do_insn_write")
1312      ()
1315 (dni fread "Flash read"
1316      ()
1317      "fread"
1318      (+ OP6_OTHER1 (f-op6-10low #x1B))
1319      (c-call "do_flash_read")
1320      ()
1323 (dni fwrite "Flash write"
1324      ()
1325      "fwrite"
1326      (+ OP6_OTHER1 (f-op6-10low #x1A))
1327      (c-call "do_flash_write")
1328      ()
1331 (dni iread "Insn memory read"
1332      ()
1333      "iread"
1334      (+ OP6_OTHER1 (f-op6-10low #x19))
1335      (c-call "do_insn_read")
1336      ()
1339 (dni iwrite "Insn memory write"
1340      ()
1341      "iwrite"
1342      (+ OP6_OTHER1 (f-op6-10low #x18))
1343      (c-call "do_insn_write")
1344      ()
1347 (dni page "Set insn page"
1348      (EXT-SKIP-INSN)
1349      ;"page $page3"
1350      "page $addr16p"
1351      ;(+ OP6_OTHER1 (f-op6-7low #x2) page3)
1352      ;(set pabits (srl page3 13))
1353      (+ OP6_OTHER1 (f-op6-7low #x2) addr16p)
1354      (set pabits addr16p)
1355      ()
1358 (dni system "System call"
1359      ()
1360      "system"
1361      (+ OP6_OTHER1 (f-op6-10low #xff))
1362      (c-call "do_system")
1363      ()
1366 (dni reti "Return from interrupt"
1367      ()
1368      "reti #$reti3"
1369      (+ OP6_OTHER1 (f-op6-7low #x1) reti3)
1370      (c-call "do_reti" reti3)
1371      ()
1374 (dni ret "Return"
1375      ()
1376      "ret"
1377      (+ OP6_OTHER1 (f-op6-10low #x07))
1378      (sequence ((USI new_pc))
1379                (set new_pc (c-call UHI "pop_pc_stack"))
1380                (set pabits (srl new_pc 13))
1381                (set pc new_pc))
1382      ()
1385 (dni int "Software interrupt"
1386      ()
1387      "int"
1388      (+ OP6_OTHER1 (f-op6-10low #x6))
1389      (nop)
1390      ()
1393 (dni breakx "Breakpoint with extended skip"
1394      (EXT-SKIP-INSN)
1395      "breakx"
1396      (+ OP6_OTHER1 (f-op6-10low #x5))
1397      (c-call "do_break" pc)
1398      ()
1401 (dni cwdt "Clear watchdog timer"
1402      ()
1403      "cwdt"
1404      (+ OP6_OTHER1 (f-op6-10low #x4))
1405      (c-call "do_clear_wdt")
1406      ()
1409 (dni ferase "Flash erase"
1410      ()
1411      "ferase"
1412      (+ OP6_OTHER1 (f-op6-10low #x3))
1413      (c-call "do_flash_erase")
1414      ()
1417 (dni retnp "Return, no page"
1418      ()
1419      "retnp"
1420      (+ OP6_OTHER1 (f-op6-10low #x2))
1421      (sequence ((USI new_pc))
1422                (set new_pc (c-call UHI "pop_pc_stack"))
1423                (set pc new_pc))
1424      ()
1427 (dni break "Breakpoint"
1428      ()
1429      "break"
1430      (+ OP6_OTHER1 (f-op6-10low #x1))
1431      (c-call "do_break" pc)
1432      ()
1435 (dni nop "No operation"
1436      ()
1437      "nop"
1438      (+ OP6_OTHER1 (f-op6-10low #x0))
1439      (nop)
1440      ()
1442                            
1444 ; Macro instructions
1445 (dnmi sc "Skip on carry"
1446       ()
1447       "sc"
1448       (emit sb (bitno 0) (fr #xB)) ; sb status.0
1451 (dnmi snc "Skip on no carry"
1452       ()
1453       "snc"
1454       (emit snb (bitno 0) (fr #xB)) ; snb status.0
1456       
1457 (dnmi sz "Skip on zero"
1458       ()
1459       "sz"
1460       (emit sb (bitno 2) (fr #xB)) ; sb status.2
1463 (dnmi snz "Skip on no zero"
1464       ()
1465       "snz"
1466       (emit snb (bitno 2) (fr #xB)) ; snb status.2
1469 (dnmi skip "Skip always"
1470       (SKIPA)
1471       "skip"
1472       (emit snb (bitno 0) (fr 9)) ; snb pcl.0 | (pcl&1)<<12
1475 (dnmi skipb "Skip always"
1476       (SKIPA)
1477       "skip"
1478       (emit sb (bitno 0) (fr 9)) ; sb pcl.0 | (pcl&1)<<12