1; Ubicom IP2K CPU description.  -*- Scheme -*-
2; Copyright (C) 2002, 2009, 2011 Free Software Foundation, Inc.
3;
4; Contributed by Red Hat Inc;
5;
6; This file is part of the GNU Binutils.
7;
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.
12;
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.
17;
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.
22
23(define-rtl-version 0 8)
24
25(include "simplify.inc")
26
27; define-arch must appear first
28
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)
36)
37
38; Attributes.
39
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")
45)
46
47(define-attr
48  (for insn)
49  (type boolean)
50  (name SKIPA)
51  (comment "instruction is a SKIP instruction")
52)
53
54; Instruction set parameters.
55
56(define-isa
57  (name ip2k)
58  (comment "Ubicom IP2000 ISA")
59
60  (default-insn-word-bitsize 16)
61  (default-insn-bitsize 16)
62  (base-insn-bitsize 16)
63)
64
65; Cpu family definitions.
66
67
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)
74)
75
76(define-mach
77  (name ip2022)
78  (comment "Ubicom IP2022")
79  (cpu ip2kbf)
80)
81
82(define-mach
83  (name ip2022ext)
84  (comment "Ubicom IP2022 extended")
85  (cpu ip2kbf)
86)
87
88
89; Model descriptions.
90
91(define-model
92  (name ip2k) (comment "VPE 2xxx") (attrs)
93  (mach ip2022ext)
94
95  (unit u-exec "Execution Unit" ()
96	1 1 ; issue done
97	() ; state
98	() ; inputs
99	() ; outputs
100	() ; profile action (default)
101	)
102)
103
104
105; FIXME: It might simplify things to separate the execute process from the
106; one that updates the PC.
107
108; Instruction fields.
109;
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)
116
117
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))
136;)
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))
141;)
142
143
144
145; Enums.
146
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   )
158)
159
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)
166)
167
168
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   )
174)
175
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)
181)
182
183; insn-op3: bits 15-13
184(define-normal-insn-enum insn-op3 "op3 enums" () OP3_ f-op3
185  (- - - - - - CALL JMP)
186)
187
188
189  
190; Hardware pieces.
191
192; Bank-relative general purpose registers
193
194; (define-pmacro (build-reg-name n) (.splice (.str "$" n) n))
195
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  )
235
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 ))
242)
243
244
245;;(define-hardware
246;;  (name h-gpr-global)
247;;  (comment "gpr registers - global")
248;;  (type register QI (128))
249;;)
250
251; The general register
252
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 ))
260)
261
262; The hardware stack.
263; Use {push,pop}_pc_stack c-calls to operate on this hardware element.
264
265(define-hardware
266  (name h-stack)
267  (comment "hardware stack")
268  (type register UHI (16))
269)
270
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) () () ())
276
277
278; Operands
279
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)
301
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))
312
313
314
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)
319)
320
321(define-pmacro (sub-dcflag a b c)
322  (sub-cflag (sll QI a 4) (sll QI b 4) c)
323)
324
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   )
335) 
336
337
338; Instructions, in order of the "Instruction Set Map" table on
339; pp 19-20 of IP2022 spec V1.09
340
341(dni jmp "Jump"
342     ()
343     "jmp $addr16cjp"
344     (+ OP3_JMP addr16cjp)
345     (set pc (or (sll pabits 13) addr16cjp))
346     ()
347)
348
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     ()
359)
360
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     ()
368)
369
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     ()
377)
378
379(dni setb "Set bit"
380     ()
381     "setb $fr,$bitno"
382     (+ OP4_SETB bitno fr)
383     (set fr (or fr (sll 1 bitno)))
384     ()
385)
386
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     ()
393)
394
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     ()
403)
404
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     ()
413)
414
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     ()
423)
424
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     ()
435)
436
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     ()
447)
448
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     ()
458)
459
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     ()
470)
471
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     ()
479)
480
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     ()
488)
489
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))
497
498     )
499     ()
500)
501
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     ()
511)
512
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     ()
522)
523
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    ()
530)
531
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    ()
538)
539
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    ()
546)
547
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    ()
554)
555
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;;     ()
563;;)
564
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               )
590
591	       (set zbit (zflag result))
592	       (set cbit newcbit)
593	       (set fr result))
594     ()
595)
596
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     ()
609)
610
611
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     ()
641)
642
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     ()
652)
653
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     ()
663)
664
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     ()
674)
675
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     ()
706)
707
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     ()
717)
718
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     ()
731)
732
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               )
762
763
764	       (set zbit (zflag result))
765	       (set cbit newcbit)
766	       (set fr result))
767     ()
768)
769
770
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     ()
780)
781
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     ()
791)
792
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     ()
800)
801
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     ()
809)
810
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;;    ()
818;;)
819
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;;    ()
827;;)
828
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     ()
859)
860
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     ()
870)
871
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     ()
879)
880
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     ()
888)
889
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     ()
900)
901
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     ()
912)
913
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     ()
924)
925
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     ()
936)
937
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     ()
968)
969
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     ()
979)
980
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     ()
1010)
1011
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     ()
1020)
1021
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     ()
1030)
1031
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     ()
1040)
1041
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     ()
1049)
1050
1051(dni movw_l "MOV W,literal"
1052     ()
1053     "mov W,#$lit8"
1054     (+ OP4_LITERAL OP4MID_MOV_L lit8)
1055     (set w lit8)
1056     ()
1057)
1058
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     ()
1065)
1066
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     ()
1075)
1076
1077
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))
1086
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     ()
1107)
1108
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     ()
1120)
1121
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     ()
1130)
1131
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     ()
1140)
1141
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     ()
1150)
1151
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     ()
1160)
1161
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     ()
1170)
1171
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     ()
1180)
1181
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     ()
1211)
1212
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     ()
1221)
1222
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     ()
1255)
1256
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     ()
1268)
1269
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     ()
1278)
1279
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     ()
1289)
1290
1291(dni speed "Set speed"
1292     ()
1293     "speed #$lit8"
1294     (+ (f-op8 1) lit8)
1295     (set (reg h-registers #x0E) lit8)
1296     ()
1297)
1298
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     ()
1305)
1306
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     ()
1313)
1314
1315(dni fread "Flash read"
1316     ()
1317     "fread"
1318     (+ OP6_OTHER1 (f-op6-10low #x1B))
1319     (c-call "do_flash_read")
1320     ()
1321)
1322
1323(dni fwrite "Flash write"
1324     ()
1325     "fwrite"
1326     (+ OP6_OTHER1 (f-op6-10low #x1A))
1327     (c-call "do_flash_write")
1328     ()
1329)
1330
1331(dni iread "Insn memory read"
1332     ()
1333     "iread"
1334     (+ OP6_OTHER1 (f-op6-10low #x19))
1335     (c-call "do_insn_read")
1336     ()
1337)
1338
1339(dni iwrite "Insn memory write"
1340     ()
1341     "iwrite"
1342     (+ OP6_OTHER1 (f-op6-10low #x18))
1343     (c-call "do_insn_write")
1344     ()
1345)
1346
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     ()
1356)
1357
1358(dni system "System call"
1359     ()
1360     "system"
1361     (+ OP6_OTHER1 (f-op6-10low #xff))
1362     (c-call "do_system")
1363     ()
1364)
1365
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     ()
1372)
1373
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     ()
1383)
1384
1385(dni int "Software interrupt"
1386     ()
1387     "int"
1388     (+ OP6_OTHER1 (f-op6-10low #x6))
1389     (nop)
1390     ()
1391)
1392
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     ()
1399)
1400
1401(dni cwdt "Clear watchdog timer"
1402     ()
1403     "cwdt"
1404     (+ OP6_OTHER1 (f-op6-10low #x4))
1405     (c-call "do_clear_wdt")
1406     ()
1407)
1408
1409(dni ferase "Flash erase"
1410     ()
1411     "ferase"
1412     (+ OP6_OTHER1 (f-op6-10low #x3))
1413     (c-call "do_flash_erase")
1414     ()
1415)
1416
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     ()
1425)
1426
1427(dni break "Breakpoint"
1428     ()
1429     "break"
1430     (+ OP6_OTHER1 (f-op6-10low #x1))
1431     (c-call "do_break" pc)
1432     ()
1433)
1434
1435(dni nop "No operation"
1436     ()
1437     "nop"
1438     (+ OP6_OTHER1 (f-op6-10low #x0))
1439     (nop)
1440     ()
1441)
1442			   
1443
1444; Macro instructions
1445(dnmi sc "Skip on carry"
1446      ()
1447      "sc"
1448      (emit sb (bitno 0) (fr #xB)) ; sb status.0
1449)
1450
1451(dnmi snc "Skip on no carry"
1452      ()
1453      "snc"
1454      (emit snb (bitno 0) (fr #xB)) ; snb status.0
1455)
1456      
1457(dnmi sz "Skip on zero"
1458      ()
1459      "sz"
1460      (emit sb (bitno 2) (fr #xB)) ; sb status.2
1461)
1462
1463(dnmi snz "Skip on no zero"
1464      ()
1465      "snz"
1466      (emit snb (bitno 2) (fr #xB)) ; snb status.2
1467)
1468
1469(dnmi skip "Skip always"
1470      (SKIPA)
1471      "skip"
1472      (emit snb (bitno 0) (fr 9)) ; snb pcl.0 | (pcl&1)<<12
1473)
1474
1475(dnmi skipb "Skip always"
1476      (SKIPA)
1477      "skip"
1478      (emit sb (bitno 0) (fr 9)) ; sb pcl.0 | (pcl&1)<<12
1479)
1480
1481