Commit | Line | Data |
---|---|---|
dc15e575 NC |
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 | \f | |
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 | \f | |
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 | \f | |
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 | \f | |
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 |