1369 lines
35 KiB
Plaintext
1369 lines
35 KiB
Plaintext
|
|
define endian=little;
|
|
|
|
define alignment=1;
|
|
|
|
define space RAM type=ram_space size=2 wordsize=1 default;
|
|
define space register type=register_space size=1;
|
|
|
|
################################################################
|
|
# Registers
|
|
################################################################
|
|
define register offset=0x00 size=2 [ PSW ];
|
|
|
|
define register offset=0x10 size=2 [ PC ];
|
|
|
|
define register offset=0x18 size=2 [ SP ];
|
|
|
|
# Special registers
|
|
define RAM offset=0x00 size=1
|
|
[
|
|
ZRlo ZRhi AD_resultlo AD_resulthi HSI_timelo HSI_timehi
|
|
HSI_status SBUF INT_MASK INT_PEND TIMER1lo TIMER1hi
|
|
TIMER2lo TIMER2hi PORT0 PORT1 PORT2 SP_STAT INT_PEND1
|
|
INT_MASK1 WSR IOS0 IOS1 IOS2
|
|
];
|
|
|
|
define RAM offset=0x00 size=2
|
|
[
|
|
ZR AD_result HSI_time
|
|
HSI_SBUF INTERRUPT TIMER1
|
|
TIMER2 PORT01 PORT2_SPS INT1
|
|
WSR_IOS0 IOS12
|
|
];
|
|
|
|
define RAM offset=0x00 size=4
|
|
[
|
|
ZR_AD HSI INT_TIMER1
|
|
TIMER2_PORT01 PORT2_INT1
|
|
WSR_IOS012
|
|
];
|
|
|
|
# Stack pointer
|
|
define RAM offset=0x18 size=1 [ SPlo SPhi];
|
|
define RAM offset=0x18 size=2 [ SPR ];
|
|
define RAM offset=0x18 size=4 [ SPR1A ];
|
|
|
|
|
|
# Byte registers
|
|
define RAM offset=0x1a size=1
|
|
[
|
|
R1A R1B R1C R1D R1E R1F
|
|
R20 R21 R22 R23 R24 R25 R26 R27
|
|
R28 R29 R2A R2B R2C R2D R2E R2F
|
|
R30 R31 R32 R33 R34 R35 R36 R37
|
|
R38 R39 R3A R3B R3C R3D R3E R3F
|
|
R40 R41 R42 R43 R44 R45 R46 R47
|
|
R48 R49 R4A R4B R4C R4D R4E R4F
|
|
R50 R51 R52 R53 R54 R55 R56 R57
|
|
R58 R59 R5A R5B R5C R5D R5E R5F
|
|
R60 R61 R62 R63 R64 R65 R66 R67
|
|
R68 R69 R6A R6B R6C R6D R6E R6F
|
|
R70 R71 R72 R73 R74 R75 R76 R77
|
|
R78 R79 R7A R7B R7C R7D R7E R7F
|
|
R80 R81 R82 R83 R84 R85 R86 R87
|
|
R88 R89 R8A R8B R8C R8D R8E R8F
|
|
R90 R91 R92 R93 R94 R95 R96 R97
|
|
R98 R99 R9A R9B R9C R9D R9E R9F
|
|
RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7
|
|
RA8 RA9 RAA RAB RAC RAD RAE RAF
|
|
RB0 RB1 RB2 RB3 RB4 RB5 RB6 RB7
|
|
RB8 RB9 RBA RBB RBC RBD RBE RBF
|
|
RC0 RC1 RC2 RC3 RC4 RC5 RC6 RC7
|
|
RC8 RC9 RCA RCB RCC RCD RCE RCF
|
|
RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7
|
|
RD8 RD9 RDA RDB RDC RDD RDE RDF
|
|
RE0 RE1 RE2 RE3 RE4 RE5 RE6 RE7
|
|
RE8 RE9 REA REB REC RED REE REF
|
|
RF0 RF1 RF2 RF3 RF4 RF5 RF6 RF7
|
|
RF8 RF9 RFA RFB RFC RFD RFE RFF
|
|
R100 R101 R102 R103 R104 R105 R106 R107
|
|
R108 R109 R10A R10B R10C R10D R10E R10F
|
|
R110 R111 R112 R113 R114 R115 R116 R117
|
|
R118 R119 R11A R11B R11C R11D R11E R11F
|
|
R120 R121 R122 R123 R124 R125 R126 R127
|
|
R128 R129 R12A R12B R12C R12D R12E R12F
|
|
R130 R131 R132 R133 R134 R135 R136 R137
|
|
R138 R139 R13A R13B R13C R13D R13E R13F
|
|
R140 R141 R142 R143 R144 R145 R146 R147
|
|
R148 R149 R14A R14B R14C R14D R14E R14F
|
|
R150 R151 R152 R153 R154 R155 R156 R157
|
|
R158 R159 R15A R15B R15C R15D R15E R15F
|
|
R160 R161 R162 R163 R164 R165 R166 R167
|
|
R168 R169 R16A R16B R16C R16D R16E R16F
|
|
R170 R171 R172 R173 R174 R175 R176 R177
|
|
R178 R179 R17A R17B R17C R17D R17E R17F
|
|
R180 R181 R182 R183 R184 R185 R186 R187
|
|
R188 R189 R18A R18B R18C R18D R18E R18F
|
|
R190 R191 R192 R193 R194 R195 R196 R197
|
|
R198 R199 R19A R19B R19C R19D R19E R19F
|
|
R1A0 R1A1 R1A2 R1A3 R1A4 R1A5 R1A6 R1A7
|
|
R1A8 R1A9 R1AA R1AB R1AC R1AD R1AE R1AF
|
|
R1B0 R1B1 R1B2 R1B3 R1B4 R1B5 R1B6 R1B7
|
|
R1B8 R1B9 R1BA R1BB R1BC R1BD R1BE R1BF
|
|
R1C0 R1C1 R1C2 R1C3 R1C4 R1C5 R1C6 R1C7
|
|
R1C8 R1C9 R1CA R1CB R1CC R1CD R1CE R1CF
|
|
R1D0 R1D1 R1D2 R1D3 R1D4 R1D5 R1D6 R1D7
|
|
R1D8 R1D9 R1DA R1DB R1DC R1DD R1DE R1DF
|
|
R1E0 R1E1 R1E2 R1E3 R1E4 R1E5 R1E6 R1E7
|
|
R1E8 R1E9 R1EA R1EB R1EC R1ED R1EE R1EF
|
|
R1F0 R1F1 R1F2 R1F3 R1F4 R1F5 R1F6 R1F7
|
|
R1F8 R1F9 R1FA R1FB R1FC R1FD R1FE R1FF
|
|
];
|
|
|
|
# Word registers
|
|
define RAM offset=0x1a size=2
|
|
[
|
|
RW1A RW1C RW1E
|
|
RW20 RW22 RW24 RW26 RW28 RW2A RW2C RW2E
|
|
RW30 RW32 RW34 RW36 RW38 RW3A RW3C RW3E
|
|
RW40 RW42 RW44 RW46 RW48 RW4A RW4C RW4E
|
|
RW50 RW52 RW54 RW56 RW58 RW5A RW5C RW5E
|
|
RW60 RW62 RW64 RW66 RW68 RW6A RW6C RW6E
|
|
RW70 RW72 RW74 RW76 RW78 RW7A RW7C RW7E
|
|
RW80 RW82 RW84 RW86 RW88 RW8A RW8C RW8E
|
|
RW90 RW92 RW94 RW96 RW98 RW9A RW9C RW9E
|
|
RWA0 RWA2 RWA4 RWA6 RWA8 RWAA RWAC RWAE
|
|
RWB0 RWB2 RWB4 RWB6 RWB8 RWBA RWBC RWBE
|
|
RWC0 RWC2 RWC4 RWC6 RWC8 RWCA RWCC RWCE
|
|
RWD0 RWD2 RWD4 RWD6 RWD8 RWDA RWDC RWDE
|
|
RWE0 RWE2 RWE4 RWE6 RWE8 RWEA RWEC RWEE
|
|
RWF0 RWF2 RWF4 RWF6 RWF8 RWFA RWFC RWFE
|
|
RW100 RW102 RW104 RW106 RW108 RW10A RW10C RW10E
|
|
RW110 RW112 RW114 RW116 RW118 RW11A RW11C RW11E
|
|
RW120 RW122 RW124 RW126 RW128 RW12A RW12C RW12E
|
|
RW130 RW132 RW134 RW136 RW138 RW13A RW13C RW13E
|
|
RW140 RW142 RW144 RW146 RW148 RW14A RW14C RW14E
|
|
RW150 RW152 RW154 RW156 RW158 RW15A RW15C RW15E
|
|
RW160 RW162 RW164 RW166 RW168 RW16A RW16C RW16E
|
|
RW170 RW172 RW174 RW176 RW178 RW17A RW17C RW17E
|
|
RW180 RW182 RW184 RW186 RW188 RW18A RW18C RW18E
|
|
RW190 RW192 RW194 RW196 RW198 RW19A RW19C RW19E
|
|
RW1A0 RW1A2 RW1A4 RW1A6 RW1A8 RW1AA RW1AC RW1AE
|
|
RW1B0 RW1B2 RW1B4 RW1B6 RW1B8 RW1BA RW1BC RW1BE
|
|
RW1C0 RW1C2 RW1C4 RW1C6 RW1C8 RW1CA RW1CC RW1CE
|
|
RW1D0 RW1D2 RW1D4 RW1D6 RW1D8 RW1DA RW1DC RW1DE
|
|
RW1E0 RW1E2 RW1E4 RW1E6 RW1E8 RW1EA RW1EC RW1EE
|
|
RW1F0 RW1F2 RW1F4 RW1F6 RW1F8 RW1FA RW1FC RW1FE
|
|
];
|
|
|
|
# Double-word registers
|
|
define RAM offset=0x1c size=4
|
|
[
|
|
RL1C
|
|
RL20 RL24 RL28 RL2C RL30 RL34 RL38 RL3C
|
|
RL40 RL44 RL48 RL4C RL50 RL54 RL58 RL5C
|
|
RL60 RL64 RL68 RL6C RL70 RL74 RL78 RL7C
|
|
RL80 RL84 RL88 RL8C RL90 RL94 RL98 RL9C
|
|
RLA0 RLA4 RLA8 RLAC RLB0 RLB4 RLB8 RLBC
|
|
RLC0 RLC4 RLC8 RLCC RLD0 RLD4 RLD8 RLDC
|
|
RLE0 RLE4 RLE8 RLEC RLF0 RLF4 RLF8 RLFC
|
|
RL100 RL104 RL108 RL10C RL110 RL114 RL118 RL11C
|
|
RL120 RL124 RL128 RL12C RL130 RL134 RL138 RL13C
|
|
RL140 RL144 RL148 RL14C RL150 RL154 RL158 RL15C
|
|
RL160 RL164 RL168 RL16C RL170 RL174 RL178 RL17C
|
|
RL180 RL184 RL188 RL18C RL190 RL194 RL198 RL19C
|
|
RL1A0 RL1A4 RL1A8 RL1AC RL1B0 RL1B4 RL1B8 RL1BC
|
|
RL1C0 RL1C4 RL1C8 RL1CC RL1D0 RL1D4 RL1D8 RL1DC
|
|
RL1E0 RL1E4 RL1E8 RL1EC RL1F0 RL1F4 RL1F8 RL1FC
|
|
];
|
|
|
|
# Individual status bits within the Program Status Word
|
|
@define Z "PSW[7,1]" # Zero Flag
|
|
@define N "PSW[6,1]" # Negative Flag
|
|
@define V "PSW[5,1]" # Overflow Flag
|
|
@define VT "PSW[4,1]" # Overflow Trap Flag
|
|
@define C "PSW[3,1]" # Carry Flag
|
|
@define PSE "PSW[2,1]" # Peripheral Transaction Server flag
|
|
@define I "PSW[1,1]" # global Interrupt disable bit
|
|
@define ST "PSW[0,1]" # STicky bit Flag
|
|
|
|
################################################################
|
|
# Tokens
|
|
################################################################
|
|
# All instructions have a single-byte opcode except for a
|
|
# handful of multiplication/division instructions which have
|
|
# a two-byte op-code with the first byte as 'FE'
|
|
define token opbyte (8)
|
|
op8 = (0,7)
|
|
op6 = (2,7)
|
|
op5 = (3,7)
|
|
cond = (0,3)
|
|
op4 = (4,7)
|
|
aa = (0,1)
|
|
bitno = (0,2)
|
|
highb = (4,7)
|
|
imm8 = (0,7) signed # immediate
|
|
simm8 = (0,7) signed # immediate
|
|
baop = (0,7) # byte register
|
|
breg8 = (0,7) # byte register
|
|
dbreg = (0,7) # byte register
|
|
waop = (0,7) # word register
|
|
wreg8 = (0,7) # word register
|
|
dwreg = (0,7) # word register
|
|
lreg = (0,7) # long/double register
|
|
dlreg = (0,7) # long/double register
|
|
imm7 = (1,7)
|
|
iwreg7 = (1,7)
|
|
addbit8 = (0,0)
|
|
;
|
|
|
|
define token opword (16)
|
|
imm16 = ( 0, 15 )
|
|
disp16 = (0,15) signed
|
|
op16 = (3,7)
|
|
jmp11_hi = (0,2) signed #relative offset
|
|
jmp11_lo = (8,15)
|
|
;
|
|
|
|
attach variables [ baop breg8 dbreg ]
|
|
[
|
|
ZRlo ZRhi AD_resultlo AD_resulthi HSI_timelo HSI_timehi
|
|
HSI_status SBUF INT_MASK INT_PEND TIMER1lo TIMER1hi
|
|
TIMER2lo TIMER2hi PORT0 PORT1 PORT2 SP_STAT INT_PEND1
|
|
INT_MASK1 WSR IOS0 IOS1 IOS2 SPlo SPhi
|
|
R1A R1B R1C R1D R1E R1F
|
|
R20 R21 R22 R23 R24 R25 R26 R27
|
|
R28 R29 R2A R2B R2C R2D R2E R2F
|
|
R30 R31 R32 R33 R34 R35 R36 R37
|
|
R38 R39 R3A R3B R3C R3D R3E R3F
|
|
R40 R41 R42 R43 R44 R45 R46 R47
|
|
R48 R49 R4A R4B R4C R4D R4E R4F
|
|
R50 R51 R52 R53 R54 R55 R56 R57
|
|
R58 R59 R5A R5B R5C R5D R5E R5F
|
|
R60 R61 R62 R63 R64 R65 R66 R67
|
|
R68 R69 R6A R6B R6C R6D R6E R6F
|
|
R70 R71 R72 R73 R74 R75 R76 R77
|
|
R78 R79 R7A R7B R7C R7D R7E R7F
|
|
R80 R81 R82 R83 R84 R85 R86 R87
|
|
R88 R89 R8A R8B R8C R8D R8E R8F
|
|
R90 R91 R92 R93 R94 R95 R96 R97
|
|
R98 R99 R9A R9B R9C R9D R9E R9F
|
|
RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7
|
|
RA8 RA9 RAA RAB RAC RAD RAE RAF
|
|
RB0 RB1 RB2 RB3 RB4 RB5 RB6 RB7
|
|
RB8 RB9 RBA RBB RBC RBD RBE RBF
|
|
RC0 RC1 RC2 RC3 RC4 RC5 RC6 RC7
|
|
RC8 RC9 RCA RCB RCC RCD RCE RCF
|
|
RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7
|
|
RD8 RD9 RDA RDB RDC RDD RDE RDF
|
|
RE0 RE1 RE2 RE3 RE4 RE5 RE6 RE7
|
|
RE8 RE9 REA REB REC RED REE REF
|
|
RF0 RF1 RF2 RF3 RF4 RF5 RF6 RF7
|
|
RF8 RF9 RFA RFB RFC RFD RFE RFF
|
|
];
|
|
|
|
attach variables [ waop wreg8 dwreg ]
|
|
[
|
|
ZR _ AD_result _ HSI_time _
|
|
HSI_SBUF _ INTERRUPT _ TIMER1 _
|
|
TIMER2 _ PORT01 _ PORT2_SPS _ INT1 _
|
|
WSR_IOS0 _ IOS12 _ SP _
|
|
RW1A _ RW1C _ RW1E _
|
|
RW20 _ RW22 _ RW24 _ RW26 _ RW28 _ RW2A _ RW2C _ RW2E _
|
|
RW30 _ RW32 _ RW34 _ RW36 _ RW38 _ RW3A _ RW3C _ RW3E _
|
|
RW40 _ RW42 _ RW44 _ RW46 _ RW48 _ RW4A _ RW4C _ RW4E _
|
|
RW50 _ RW52 _ RW54 _ RW56 _ RW58 _ RW5A _ RW5C _ RW5E _
|
|
RW60 _ RW62 _ RW64 _ RW66 _ RW68 _ RW6A _ RW6C _ RW6E _
|
|
RW70 _ RW72 _ RW74 _ RW76 _ RW78 _ RW7A _ RW7C _ RW7E _
|
|
RW80 _ RW82 _ RW84 _ RW86 _ RW88 _ RW8A _ RW8C _ RW8E _
|
|
RW90 _ RW92 _ RW94 _ RW96 _ RW98 _ RW9A _ RW9C _ RW9E _
|
|
RWA0 _ RWA2 _ RWA4 _ RWA6 _ RWA8 _ RWAA _ RWAC _ RWAE _
|
|
RWB0 _ RWB2 _ RWB4 _ RWB6 _ RWB8 _ RWBA _ RWBC _ RWBE _
|
|
RWC0 _ RWC2 _ RWC4 _ RWC6 _ RWC8 _ RWCA _ RWCC _ RWCE _
|
|
RWD0 _ RWD2 _ RWD4 _ RWD6 _ RWD8 _ RWDA _ RWDC _ RWDE _
|
|
RWE0 _ RWE2 _ RWE4 _ RWE6 _ RWE8 _ RWEA _ RWEC _ RWEE _
|
|
RWF0 _ RWF2 _ RWF4 _ RWF6 _ RWF8 _ RWFA _ RWFC _ RWFE _
|
|
];
|
|
|
|
attach variables [iwreg7]
|
|
[
|
|
ZR AD_result HSI_time
|
|
HSI_SBUF INTERRUPT TIMER1
|
|
TIMER2 PORT01 PORT2_SPS INT1
|
|
WSR_IOS0 IOS12 SP
|
|
RW1A RW1C RW1E
|
|
RW20 RW22 RW24 RW26 RW28 RW2A RW2C RW2E
|
|
RW30 RW32 RW34 RW36 RW38 RW3A RW3C RW3E
|
|
RW40 RW42 RW44 RW46 RW48 RW4A RW4C RW4E
|
|
RW50 RW52 RW54 RW56 RW58 RW5A RW5C RW5E
|
|
RW60 RW62 RW64 RW66 RW68 RW6A RW6C RW6E
|
|
RW70 RW72 RW74 RW76 RW78 RW7A RW7C RW7E
|
|
RW80 RW82 RW84 RW86 RW88 RW8A RW8C RW8E
|
|
RW90 RW92 RW94 RW96 RW98 RW9A RW9C RW9E
|
|
RWA0 RWA2 RWA4 RWA6 RWA8 RWAA RWAC RWAE
|
|
RWB0 RWB2 RWB4 RWB6 RWB8 RWBA RWBC RWBE
|
|
RWC0 RWC2 RWC4 RWC6 RWC8 RWCA RWCC RWCE
|
|
RWD0 RWD2 RWD4 RWD6 RWD8 RWDA RWDC RWDE
|
|
RWE0 RWE2 RWE4 RWE6 RWE8 RWEA RWEC RWEE
|
|
RWF0 RWF2 RWF4 RWF6 RWF8 RWFA RWFC RWFE
|
|
];
|
|
|
|
attach variables [ lreg dlreg ]
|
|
[
|
|
ZR_AD _ _ _ HSI _ _ _ INT_TIMER1 _ _ _
|
|
TIMER2_PORT01 _ _ _ PORT2_INT1 _ _ _
|
|
WSR_IOS012 _ _ _ SPR1A _ _ _
|
|
RL1C _ _ _
|
|
RL20 _ _ _ RL24 _ _ _ RL28 _ _ _ RL2C _ _ _ RL30 _ _ _ RL34 _ _ _ RL38 _ _ _ RL3C _ _ _
|
|
RL40 _ _ _ RL44 _ _ _ RL48 _ _ _ RL4C _ _ _ RL50 _ _ _ RL54 _ _ _ RL58 _ _ _ RL5C _ _ _
|
|
RL60 _ _ _ RL64 _ _ _ RL68 _ _ _ RL6C _ _ _ RL70 _ _ _ RL74 _ _ _ RL78 _ _ _ RL7C _ _ _
|
|
RL80 _ _ _ RL84 _ _ _ RL88 _ _ _ RL8C _ _ _ RL90 _ _ _ RL94 _ _ _ RL98 _ _ _ RL9C _ _ _
|
|
RLA0 _ _ _ RLA4 _ _ _ RLA8 _ _ _ RLAC _ _ _ RLB0 _ _ _ RLB4 _ _ _ RLB8 _ _ _ RLBC _ _ _
|
|
RLC0 _ _ _ RLC4 _ _ _ RLC8 _ _ _ RLCC _ _ _ RLD0 _ _ _ RLD4 _ _ _ RLD8 _ _ _ RLDC _ _ _
|
|
RLE0 _ _ _ RLE4 _ _ _ RLE8 _ _ _ RLEC _ _ _ RLF0 _ _ _ RLF4 _ _ _ RLF8 _ _ _ RLFC _ _ _
|
|
];
|
|
|
|
immed8: imm8 is imm8 { export *[const]:1 imm8; }
|
|
|
|
simmed8: simm8 is simm8 { export *[const]:1 simm8; }
|
|
|
|
immed16: imm16 is imm16 { export *[const]:2 imm16; }
|
|
|
|
baop8: baop is baop & baop=0 { export 0:1; }
|
|
baop8: baop is baop & baop=1 { export 0:1; }
|
|
baop8: baop is baop { export baop; }
|
|
|
|
waop16: waop is waop & waop=0 { export 0:2; }
|
|
waop16: waop is waop { export waop; }
|
|
|
|
iwreg: iwreg7 is iwreg7 & iwreg7=0 { export 0:2; }
|
|
iwreg: iwreg7 is iwreg7 { export iwreg7; }
|
|
|
|
breg: breg8 is breg8 & breg8=0 { export 0:1; }
|
|
breg: breg8 is breg8 & breg8=1 { export 0:1; }
|
|
breg: breg8 is breg8 { export breg8; }
|
|
|
|
wreg: wreg8 is wreg8 & wreg8=0 { export 0:2; }
|
|
wreg: wreg8 is wreg8 { export wreg8; }
|
|
|
|
# See reference manual pp. 29-30 and note 1 on page 113
|
|
# 1-byte operands
|
|
oper8: baop8 is aa=0x0; baop8 { export baop8; } #direct
|
|
oper8: "#"immed8 is aa=0x1; immed8 { export immed8; } #immediate
|
|
oper8: "["iwreg"]" is aa=0x2; iwreg & addbit8=0 {
|
|
local tmp = iwreg;
|
|
export *[RAM]:1 tmp;
|
|
} #indirect
|
|
oper8: "["iwreg"]+" is aa=0x2; iwreg & addbit8=1 {
|
|
local tmp = iwreg;
|
|
iwreg = iwreg + 1;
|
|
export *[RAM]:1 tmp;
|
|
} #indirect+
|
|
oper8: simmed8"["iwreg"]" is aa=0x3; iwreg & addbit8=0; simmed8 {
|
|
local tmp = iwreg;
|
|
tmp = tmp + sext(simmed8);
|
|
export *[RAM]:1 tmp;
|
|
} #indexed short
|
|
oper8: immed16", LOOKUP["iwreg"]" is aa=0x3; iwreg & addbit8=1; immed16 {
|
|
local tmp = iwreg;
|
|
tmp = tmp + immed16;
|
|
export *[RAM]:1 tmp;
|
|
} #indexed long
|
|
|
|
# 2-byte operands
|
|
oper16: waop16 is aa=0x0; waop16 { export waop16; } #direct
|
|
oper16: "#"immed16 is aa=0x1; immed16 { export immed16; } #immediate
|
|
oper16: "["iwreg"]" is aa=0x2; iwreg & addbit8=0 {
|
|
local tmp = iwreg;
|
|
export *[RAM]:2 tmp;
|
|
} #indirect
|
|
oper16: "["iwreg"]+" is aa=0x2; iwreg & addbit8=1 {
|
|
local tmp = iwreg;
|
|
iwreg = iwreg + 2;
|
|
export *[RAM]:2 tmp;
|
|
} #indirect
|
|
oper16: simmed8"["iwreg"]" is aa=0x3; iwreg & addbit8=0; simmed8 {
|
|
local tmp = iwreg;
|
|
tmp = tmp + sext(simmed8);
|
|
export *[RAM]:2 tmp;
|
|
} #indexed short
|
|
oper16: immed16", TABLE["iwreg"]" is aa=0x3 ; iwreg & addbit8=1; immed16 {
|
|
local tmp = iwreg;
|
|
tmp = tmp + immed16;
|
|
export *[RAM]:2 tmp;
|
|
} #indexed long
|
|
|
|
# range -128 through +127
|
|
jmpdest: reloc is simm8 [ reloc = inst_next + simm8; ] { export *:1 reloc; }
|
|
|
|
# range -1023 through 1024
|
|
jmpdest11: reloc is jmp11_hi & jmp11_lo [reloc = inst_next + ((jmp11_hi << 8) | jmp11_lo);] { export *:2 reloc; }
|
|
jmpdest16: reloc is disp16 [reloc = inst_next + disp16;] { export *:2 reloc; }
|
|
|
|
################################################################
|
|
# Pseudo Instructions
|
|
################################################################
|
|
#define pcodeop blockMove;
|
|
define pcodeop idlePowerdown;
|
|
define pcodeop normalize;
|
|
|
|
################################################################
|
|
# Macros
|
|
################################################################
|
|
macro push(val) {
|
|
SP = SP - 2;
|
|
*:2 SP = val;
|
|
}
|
|
|
|
macro pop(val) {
|
|
val = *:2 SP;
|
|
SP = SP + 2;
|
|
}
|
|
|
|
macro resetFlags() {
|
|
PSW = 0;
|
|
}
|
|
|
|
macro resultFlags(res) {
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(C) = 0;
|
|
$(V) = 0;
|
|
}
|
|
|
|
macro additionFlags(op1, op2, res) {
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(C) = carry(op1, op2);
|
|
$(V) = scarry(op1, op2);
|
|
$(VT) = $(V) | $(VT);
|
|
}
|
|
|
|
macro subtractFlags(op1, op2, res) {
|
|
$(N) = (res s< 0);
|
|
$(Z) = (res == 0);
|
|
$(C) = (op1 < op2) == 0;
|
|
$(V) = sborrow(op1, op2);
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
macro stickyFlagW(source, shift) {
|
|
local mask:2 = -1;
|
|
mask = (mask >> (16 - shift + 1)) * zext(shift > 1);
|
|
local result:2 = source & mask;
|
|
|
|
$(ST) = (result != 0);
|
|
}
|
|
|
|
macro stickyFlagB(source, shift) {
|
|
local mask:1 = -1;
|
|
mask = (mask >> (8 - shift + 1)) * (shift > 1);
|
|
local result:1 = source & mask;
|
|
|
|
$(ST) = (result != 0);
|
|
}
|
|
|
|
macro stickyFlagL(source, shift) {
|
|
local mask:4 = -1;
|
|
mask = (mask >> (32 - shift + 1)) * zext(shift > 1);
|
|
local result:4 = source & mask;
|
|
|
|
$(ST) = (result != 0);
|
|
}
|
|
|
|
macro blockMove(ptrs, cntreg) {
|
|
local tsptr:4 = (ptrs & 0xffff0000) >> 0x10;
|
|
local srcPtr:2 = tsptr(2);
|
|
local dstPtr:2 = ptrs(2);
|
|
local cnt = cntreg;
|
|
<loop>
|
|
local data:2 = *srcPtr;
|
|
*dstPtr = data;
|
|
srcPtr = srcPtr + 2;
|
|
dstPtr = dstPtr + 2;
|
|
cnt = cnt - 1;
|
|
if cnt != 0 goto <loop>;
|
|
ptrs = zext(dstPtr) | (zext(srcPtr) << 0x10);
|
|
}
|
|
|
|
macro setShiftLeftCarryFlag(shiftee,amount) {
|
|
shifting:1 = amount != 0;
|
|
local tmp = ((shiftee >> (16-amount)) & 1);
|
|
$(C) = (shifting & tmp:1);
|
|
}
|
|
|
|
macro setShiftRightCarryFlag(shiftee,amount) {
|
|
shifting:1 = amount != 0;
|
|
local tmp = (shiftee >> (amount-1)) & 1;
|
|
$(C) = (shifting & tmp:1);
|
|
}
|
|
|
|
macro setSignedShiftRightCarryFlag(shiftee,amount) {
|
|
shifting:1 = amount != 0;
|
|
local tmp = (shiftee s>> (amount-1)) & 1;
|
|
$(C) = (shifting & tmp:1);
|
|
}
|
|
|
|
################################################################
|
|
# Constructors
|
|
################################################################
|
|
# 2-op
|
|
:ADD wreg, oper16 is op6=0x19 ... & oper16; wreg {
|
|
local tmpD = wreg + oper16;
|
|
additionFlags(wreg, oper16, tmpD);
|
|
wreg = tmpD;
|
|
}
|
|
|
|
# 3 op
|
|
:ADD dwreg, wreg, oper16 is op6=0x11 ... & oper16; wreg; dwreg {
|
|
local tmpD = wreg + oper16;
|
|
dwreg = tmpD;
|
|
additionFlags(wreg, oper16, tmpD);
|
|
}
|
|
|
|
# 2-op
|
|
:ADDB breg, oper8 is op6=0x1d ... & oper8; breg {
|
|
local tmp = breg + oper8;
|
|
additionFlags(breg, oper8, tmp);
|
|
breg = tmp;
|
|
}
|
|
|
|
:ADDB dbreg, breg, oper8 is op6=0x15 ... & oper8; breg; dbreg {
|
|
local tmp = breg + oper8;
|
|
dbreg = tmp;
|
|
additionFlags(breg, oper8, tmp);
|
|
}
|
|
|
|
:ADDC wreg, oper16 is op6=0x29 ... & oper16; wreg {
|
|
local tmp = oper16 + zext($(C));
|
|
local res = wreg + tmp;
|
|
local oldz = $(Z);
|
|
additionFlags(wreg, tmp, res);
|
|
$(Z) = oldz & $(Z); # only cleared, not set
|
|
wreg = res;
|
|
}
|
|
|
|
:ADDCB breg, oper8 is op6=0x2d ... & oper8; breg {
|
|
local tmp = oper8 + $(C);
|
|
local res =breg + tmp;
|
|
local oldz = $(Z);
|
|
additionFlags(breg, tmp, res);
|
|
$(Z) = oldz & $(Z); # only cleared, not set
|
|
breg = res;
|
|
}
|
|
|
|
# 2-op
|
|
:AND wreg, oper16 is op6=0x18 ... & oper16; wreg {
|
|
wreg = wreg & oper16;
|
|
resultFlags(wreg);
|
|
}
|
|
|
|
# 3-op
|
|
:AND dwreg, wreg, oper16 is op6=0x10 ... & oper16; wreg; dwreg {
|
|
dwreg = wreg & oper16;
|
|
resultFlags(dwreg);
|
|
}
|
|
|
|
:ANDB breg, oper8 is op6=0x1c ... & oper8; breg {
|
|
breg = breg & oper8;
|
|
resultFlags(breg);
|
|
}
|
|
|
|
:ANDB dbreg, breg, oper8 is op6=0x14 ... & oper8; breg; dbreg {
|
|
dbreg = breg & oper8;
|
|
resultFlags(dbreg);
|
|
}
|
|
|
|
:BMOV lreg, wreg is op8=0xc1; wreg ; lreg {
|
|
blockMove(lreg, wreg);
|
|
}
|
|
|
|
:BMOVI lreg, wreg is op8=0xcd; wreg; lreg {
|
|
blockMove(lreg, wreg);
|
|
}
|
|
|
|
:BR [ wreg ] is op8=0xe3; wreg {
|
|
goto [wreg];
|
|
}
|
|
|
|
:CLR wreg is op8=0x1; wreg {
|
|
wreg = 0;
|
|
$(Z) = 1;
|
|
$(N) = 0;
|
|
$(C) = 0;
|
|
$(V) = 0;
|
|
}
|
|
|
|
:CLRB breg is op8=0x11; breg {
|
|
breg = 0;
|
|
$(Z) = 1;
|
|
$(N) = 0;
|
|
$(C) = 0;
|
|
$(V) = 0;
|
|
}
|
|
|
|
:CLRC is op8=0xf8 {
|
|
$(C) = 0;
|
|
}
|
|
|
|
:CLRVT is op8=0xfc {
|
|
$(VT) = 0;
|
|
}
|
|
|
|
:CMP wreg, oper16 is op6=0x22 ... & oper16; wreg {
|
|
op1:2 = oper16;
|
|
tmp:2 = wreg - op1;
|
|
subtractFlags(wreg, op1, tmp);
|
|
}
|
|
|
|
:CMPB breg, oper8 is op6=0x26 ... & oper8; breg {
|
|
op1:1 = oper8;
|
|
tmp:1 = breg - op1;
|
|
subtractFlags(breg, op1, tmp);
|
|
}
|
|
|
|
@if defined(C196KB) || defined(C196KC)
|
|
:CMPL dlreg, lreg is op8=0xc5; lreg; dlreg {
|
|
op1:4 = lreg;
|
|
tmp:4 = dlreg - op1;
|
|
$(N) = (tmp s< 0);
|
|
$(Z) = (tmp == 0);
|
|
$(C) = scarry(dlreg, op1);
|
|
$(V) = (((dlreg & ~op1 & ~tmp) | (~dlreg & op1 & tmp)) & 0x80000000 ) != 0;
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
@endif
|
|
|
|
:DEC wreg is op8=0x05; wreg {
|
|
local tmp = wreg - 1;
|
|
subtractFlags(wreg, 1, tmp);
|
|
wreg = tmp;
|
|
}
|
|
|
|
:DECB breg is op8=0x15; breg {
|
|
local tmp = breg - 1;
|
|
subtractFlags(breg, 1, tmp);
|
|
breg = tmp;
|
|
}
|
|
|
|
:DI is op8=0xfa {
|
|
$(I) = 0;
|
|
}
|
|
|
|
:DIV lreg, oper16 is op8=0xfe; op6=0x23 ... & oper16; lreg {
|
|
local num = lreg;
|
|
local den = oper16;
|
|
local div = num s/ sext(den);
|
|
local rem = num s% sext(den);
|
|
lreg = zext(div:2 << 16) | rem;
|
|
@if defined(C196KB) || defined(C196KC)
|
|
$(V) = ((div s> 0x7fff) | (div s< 0x8001));
|
|
@endif
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
:DIVB wreg, oper8 is op8=0xfe; op6=0x27 ... & oper8; wreg {
|
|
local num = wreg;
|
|
local den = oper8;
|
|
local div = num s/ sext(den);
|
|
local rem = num s% sext(den);
|
|
wreg = zext(div:1 << 8) | rem;
|
|
@if defined(C196KB) || defined(C196KC)
|
|
$(V) = ((div s> 0x7f) | (div s< 0x81));
|
|
@endif
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
:DIVU lreg, oper16 is op6=0x23 ... & oper16; lreg {
|
|
local num = lreg;
|
|
local den = oper16;
|
|
local div = num / zext(den);
|
|
local rem = num % zext(den);
|
|
lreg = zext(div:2 << 16) | rem;
|
|
$(V) = (div > 0xffff);
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
:DIVUB wreg, oper8 is op6=0x27 ... & oper8; wreg {
|
|
local num = wreg;
|
|
local den = oper8;
|
|
local div = num / zext(den);
|
|
local rem = num % zext(den);
|
|
wreg = zext(div:1 << 8) | rem;
|
|
$(V) = (div > 0xff);
|
|
$(VT) = $(VT) | $(V);
|
|
}
|
|
|
|
:DJNZ breg, jmpdest is op8=0xe0; breg; jmpdest {
|
|
breg = breg - 1;
|
|
if (breg != 0) goto jmpdest;
|
|
}
|
|
|
|
@if defined(C196KB) || defined(C196KC)
|
|
:DJNZW wreg, jmpdest is op8=0xe1; wreg; jmpdest {
|
|
wreg = wreg - 1;
|
|
if (wreg != 0) goto jmpdest;
|
|
}
|
|
|
|
@endif
|
|
|
|
@if defined(C196KC)
|
|
:DPTS is op8=0xec {
|
|
$(PSE) = 0;
|
|
}
|
|
|
|
@endif
|
|
|
|
:EI is op8=0xfb {
|
|
$(I) = 1;
|
|
}
|
|
|
|
@if defined(C196KC)
|
|
:EPTS is op8=0xed {
|
|
$(PSE) = 1;
|
|
}
|
|
|
|
@endif
|
|
|
|
:EXT lreg is op8=0x6; lreg {
|
|
tmp:4 = lreg & 0xffff;
|
|
lreg = sext(tmp);
|
|
resultFlags(lreg);
|
|
}
|
|
|
|
:EXTB wreg is op8=0x16; wreg {
|
|
tmp:2 = wreg & 0xff;
|
|
wreg = sext(tmp);
|
|
resultFlags(wreg);
|
|
}
|
|
|
|
:INC wreg is op8=0x7; wreg {
|
|
local tmp = wreg + 1;
|
|
additionFlags(wreg, 1, tmp);
|
|
wreg = tmp;
|
|
}
|
|
|
|
:INCB breg is op8=0x17; breg {
|
|
local tmp = breg + 1;
|
|
additionFlags(breg, 1, tmp);
|
|
breg = tmp;
|
|
}
|
|
|
|
@if defined(C196KB) || defined(C196KC)
|
|
:IDLPD "#"immed8 is op8=0xf6; immed8 {
|
|
idlePowerdown();
|
|
$(Z) = 0;
|
|
$(N) = 0;
|
|
$(C) = 0;
|
|
$(V) = 0;
|
|
$(VT) = 0;
|
|
$(ST) = 0;
|
|
}
|
|
|
|
@endif
|
|
|
|
:JBC breg, bitno, jmpdest is op5=0x6 & bitno; breg; jmpdest {
|
|
local bit = (breg >> bitno) & 0x1;
|
|
if (bit == 0) goto jmpdest;
|
|
}
|
|
|
|
:JBS breg, bitno, jmpdest is op5=0x7 & bitno; breg; jmpdest {
|
|
local bit = (breg >> bitno) & 0x1;
|
|
if (bit == 1) goto jmpdest;
|
|
}
|
|
|
|
cc: "NST" is cond=0 { tmp:1 = ($(ST) == 0); export tmp; }
|
|
cc: "NH" is cond=1 { tmp:1 = (($(C) == 0) | ($(Z) == 1)); export tmp; }
|
|
cc: "GT" is cond=2 { tmp:1 = (($(N) == 0) & ($(Z) == 0)); export tmp; }
|
|
cc: "NC" is cond=3 { tmp:1 = ($(C) == 0); export tmp; }
|
|
cc: "NVT" is cond=4 { tmp:1 = ($(VT) == 0); $(VT) = 0; export tmp; }
|
|
cc: "NV" is cond=5 { tmp:1 = ($(V) == 0); export tmp; }
|
|
cc: "GE" is cond=6 { tmp:1 = ($(N) == 0); export tmp; }
|
|
cc: "NE" is cond=7 { tmp:1 = ($(Z) == 0); export tmp; }
|
|
cc: "ST" is cond=8 { tmp:1 = ($(ST) == 1); export tmp; }
|
|
cc: "H" is cond=9 { tmp:1 = (($(C) == 1) & ($(Z) == 0)); export tmp; }
|
|
cc: "LE" is cond=10 { tmp:1 = (($(N) == 1) | ($(Z) == 1)); export tmp; }
|
|
cc: "C" is cond=11 { tmp:1 = ($(C) == 1); export tmp; }
|
|
cc: "VT" is cond=12 { tmp:1 = ($(VT) == 1); $(VT) = 0; export tmp; }
|
|
cc: "V" is cond=13 { tmp:1 = ($(V) == 1); export tmp; }
|
|
cc: "LT" is cond=14 { tmp:1 = ($(N) == 1); export tmp; }
|
|
cc: "E" is cond=15 { tmp:1 = ($(Z) == 1); export tmp; }
|
|
|
|
:J^cc jmpdest is op4=0xd & cc; jmpdest
|
|
{if (cc) goto jmpdest;}
|
|
|
|
|
|
:LCALL jmpdest16 is op8=0xef; jmpdest16 {
|
|
ret:2 = inst_next;
|
|
push(ret);
|
|
call jmpdest16;
|
|
}
|
|
|
|
:LD wreg, oper16 is op6=0x28 ... & oper16; wreg {
|
|
wreg = oper16;
|
|
}
|
|
|
|
:LDB breg, oper8 is op6=0x2c ... & oper8; breg {
|
|
breg = oper8;
|
|
}
|
|
|
|
:LDBSE wreg, oper8 is op6=0x2f ... & oper8; wreg {
|
|
wreg = sext(oper8);
|
|
}
|
|
|
|
:LDBZE wreg, oper8 is op6=0x2b ... & oper8; wreg {
|
|
wreg = zext(oper8);
|
|
}
|
|
|
|
:LJMP jmpdest16 is op8=0xe7; jmpdest16 {
|
|
goto jmpdest16;
|
|
}
|
|
|
|
# 2-op
|
|
:MUL lreg, oper16 is op8=0xfe; op6=0x1b ... & oper16; lreg {
|
|
tmpD:4 = sext(lreg:2);
|
|
tmpS:4 = sext(oper16);
|
|
tmpD = tmpD * tmpS;
|
|
lreg = tmpD;
|
|
}
|
|
|
|
# 3-op
|
|
:MUL lreg, wreg, oper16 is op8=0xfe; op6=0x13 ... & oper16; wreg; lreg {
|
|
tmpD:4 = sext(wreg);
|
|
tmpS:4 = sext(oper16);
|
|
tmpD = tmpD * tmpS;
|
|
lreg = tmpD;
|
|
}
|
|
|
|
# 2-op
|
|
:MULB wreg, oper8 is op8=0xfe; op6=0x1f ... & oper8; wreg {
|
|
tmpD:2 = sext(wreg:1);
|
|
tmpS:2 = sext(oper8);
|
|
tmpD = tmpD * tmpS;
|
|
wreg = tmpD;
|
|
}
|
|
|
|
# 3-op
|
|
:MULB wreg, breg, oper8 is op8=0xfe; op6=0x17 ... & oper8; breg; wreg {
|
|
tmpD:2 = sext(breg);
|
|
tmpS:2 = sext(oper8);
|
|
tmpD = tmpD * tmpS;
|
|
wreg = tmpD;
|
|
}
|
|
|
|
# 2-op
|
|
:MULU lreg, oper16 is op6=0x1b ... & oper16; lreg {
|
|
tmpD:4 = zext(lreg:2);
|
|
tmpS:4 = zext(oper16);
|
|
tmpD = tmpD * tmpS;
|
|
lreg = tmpD;
|
|
}
|
|
|
|
# 3-op
|
|
:MULU lreg, wreg, oper16 is op6=0x13 ... & oper16; wreg; lreg {
|
|
tmpD:4 = zext(wreg);
|
|
tmpS:4 = zext(oper16);
|
|
tmpD = tmpD * tmpS;
|
|
lreg = tmpD;
|
|
}
|
|
|
|
# 2-op
|
|
:MULUB wreg, oper8 is op6=0x1f ... & oper8; wreg {
|
|
tmpD:2 = zext(wreg:1);
|
|
tmpS:2 = zext(oper8);
|
|
tmpD = tmpD * tmpS;
|
|
wreg = tmpD;
|
|
}
|
|
|
|
# 3-op
|
|
:MULUB wreg, breg, oper8 is op6=0x17 ... & oper8; breg; wreg {
|
|
local tmpD:2 = zext(breg);
|
|
local tmpS:2 = zext(oper8);
|
|
tmpD = tmpD * tmpS;
|
|
wreg = tmpD;
|
|
}
|
|
|
|
:NEG wreg is op8=0x03; wreg {
|
|
local tmp:2 = -wreg;
|
|
local zero:2 = 0;
|
|
subtractFlags(zero, wreg, tmp);
|
|
wreg = tmp;
|
|
}
|
|
|
|
:NEGB breg is op8=0x13; breg {
|
|
local tmp:1 = -breg;
|
|
local zero:1 = 0;
|
|
subtractFlags(zero, breg, tmp);
|
|
breg = tmp;
|
|
}
|
|
|
|
:NOP is op8=0xfd { } #NOP
|
|
|
|
:NORML lreg, breg is op8=0xf; breg; lreg {
|
|
#The LONG-INTEGER operand is normalized; i.e., it is shifted to the left until its
|
|
#most significant bit is 1. If the most significant bit is still 0 after 31 shifts, the
|
|
#process stops and the zero flag is set. The number of shifts actually performed
|
|
#is stored in the second operand.
|
|
normalize(lreg, breg);
|
|
$(Z) = (lreg == 0);
|
|
$(C) = 0;
|
|
# $(N) is undefined
|
|
}
|
|
|
|
:NOT wreg is op8 = 0x2; wreg {
|
|
wreg = ~wreg;
|
|
resultFlags(wreg);
|
|
}
|
|
|
|
:NOTB breg is op8=0x12; breg {
|
|
breg = ~breg;
|
|
resultFlags(breg);
|
|
}
|
|
|
|
:OR wreg, oper16 is op6=0x20 ... & oper16; wreg {
|
|
tmpD:2 = wreg;
|
|
tmpS:2 = oper16;
|
|
tmpD = tmpD | tmpS;
|
|
wreg = tmpD;
|
|
resultFlags(wreg);
|
|
}
|
|
|
|
:ORB breg, oper8 is op6=0x24 ... & oper8; breg {
|
|
tmpD:1 = breg;
|
|
tmpS:1 = oper8;
|
|
tmpD = tmpD | tmpS;
|
|
breg = tmpD;
|
|
resultFlags(breg);
|
|
}
|
|
|
|
:POP oper16 is op6=0x33 ... & oper16 {
|
|
local result:2 = 0;
|
|
pop(result);
|
|
oper16 = result;
|
|
}
|
|
|
|
@if defined(C196KB) || defined(C196KC)
|
|
:POPA is op8=0xf5 {
|
|
local result:2 = 0;
|
|
pop(result);
|
|
WSR = result:1 & 0xff;
|
|
local resultHi = result >> 8;
|
|
INT_MASK1 = resultHi:1;
|
|
pop(result);
|
|
INT_MASK = result:1 & 0xff;
|
|
resultHi = result >> 8;
|
|
PSW = resultHi:1;
|
|
}
|
|
|
|
@endif
|
|
|
|
:POPF is op8=0xf3 {
|
|
local result:2 = 0;
|
|
pop(result);
|
|
PSW = result:1;
|
|
local resultHi = result >> 8;
|
|
INT_MASK = resultHi:1;
|
|
}
|
|
|
|
:PUSH oper16 is op6=0x32 ... & oper16 {
|
|
val:2 = oper16;
|
|
push(val);
|
|
}
|
|
|
|
@if defined(C196KB) || defined(C196KC)
|
|
:PUSHA is op8=0xf4 {
|
|
local val:2 = (zext(INT_MASK) << 8) | zext(WSR);
|
|
push(val);
|
|
val = (zext(INT_MASK) << 8) | zext(PSW);
|
|
push(val);
|
|
resetFlags();
|
|
}
|
|
|
|
@endif
|
|
|
|
:PUSHF is op8=0xf2 {
|
|
val:2 = (zext(INT_MASK) << 8) | zext(PSW);
|
|
push(val);
|
|
resetFlags();
|
|
}
|
|
|
|
:RET is op8=0xf0 {
|
|
local retDest:2 = 0;
|
|
pop(retDest);
|
|
return [retDest];
|
|
}
|
|
|
|
:RST is op8=0xff {
|
|
resetFlags();
|
|
PC = 0x2080;
|
|
goto [PC];
|
|
}
|
|
|
|
:SCALL jmpdest11 is op16=0x5 & jmpdest11 {
|
|
ret:2 = inst_next;
|
|
push(ret);
|
|
call jmpdest11;
|
|
}
|
|
|
|
:SETC is op8=0xf9 {
|
|
$(C) = 1;
|
|
}
|
|
|
|
:SHL wreg, "#"immed8 is op8=0x09; immed8 & (highb = 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = immed8;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
wreg = res;
|
|
}
|
|
|
|
:SHL wreg, breg is op8=0x09; breg & (highb != 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = breg;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
wreg = res;
|
|
}
|
|
|
|
:SHLB dbreg, "#"immed8 is op8=0x19; immed8 & (highb = 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = immed8;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
dbreg = res;
|
|
}
|
|
|
|
:SHLB dbreg, breg is op8=0x19; breg & (highb != 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = breg;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
dbreg = res;
|
|
}
|
|
|
|
:SHLL lreg, "#"immed8 is op8=0x0d; immed8 & (highb = 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = immed8;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
lreg = res;
|
|
}
|
|
|
|
:SHLL lreg, breg is op8=0x0d; breg & (highb != 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = breg;
|
|
setShiftLeftCarryFlag(source, shift);
|
|
local res = source << shift;
|
|
$(Z) = (res == 0);
|
|
$(V) = 0;
|
|
$(VT) = $(VT) | $(V);
|
|
lreg = res;
|
|
}
|
|
|
|
:SHR wreg, "#"immed8 is op8=0x08; immed8 & (highb = 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = immed8;
|
|
$(ST) = 0;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
wreg = res;
|
|
stickyFlagW(source, shift);
|
|
}
|
|
|
|
:SHR wreg, breg is op8=0x08; breg & (highb != 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = breg;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
wreg = res;
|
|
stickyFlagW(source, shift);
|
|
}
|
|
|
|
:SHRA wreg, "#"immed8 is op8=0x0a; immed8 & (highb = 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = immed8;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
wreg = res;
|
|
stickyFlagW(source, shift);
|
|
}
|
|
|
|
:SHRA wreg, breg is op8=0x0a; breg & (highb != 0x0); wreg {
|
|
local source = wreg;
|
|
local shift = breg;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
wreg = res;
|
|
stickyFlagW(source, shift);
|
|
}
|
|
|
|
:SHRAB dbreg, "#"immed8 is op8=0x1a; immed8 & (highb = 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = immed8;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
dbreg = res;
|
|
stickyFlagB(source, shift);
|
|
}
|
|
|
|
:SHRAB dbreg, breg is op8=0x1a; breg & (highb != 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = breg;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
dbreg = res;
|
|
stickyFlagB(source, shift);
|
|
}
|
|
|
|
:SHRAL lreg, "#"immed8 is op8=0x0e; immed8 & (highb = 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = immed8;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
lreg = res;
|
|
stickyFlagL(source, shift);
|
|
}
|
|
|
|
:SHRAL lreg, breg is op8=0x0e; breg & (highb != 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = breg;
|
|
setSignedShiftRightCarryFlag(source, shift);
|
|
local res = source s>> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = (res s< 0);
|
|
$(V) = 0;
|
|
lreg = res;
|
|
stickyFlagL(source, shift);
|
|
}
|
|
|
|
:SHRB dbreg, "#"immed8 is op8=0x18; immed8 & (highb = 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = immed8;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
dbreg = res;
|
|
stickyFlagB(source, shift);
|
|
}
|
|
|
|
:SHRB dbreg, breg is op8=0x18; breg & (highb != 0x0); dbreg {
|
|
local source = dbreg;
|
|
local shift = breg;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
dbreg = res;
|
|
stickyFlagB(source, shift);
|
|
}
|
|
|
|
:SHRL lreg, "#"immed8 is op8=0x0c; immed8 & (highb = 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = immed8;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
lreg = res;
|
|
stickyFlagL(source, shift);
|
|
}
|
|
|
|
:SHRL lreg, breg is op8=0x0c; breg & (highb != 0x0); lreg {
|
|
local source = lreg;
|
|
local shift = breg;
|
|
setShiftRightCarryFlag(source, shift);
|
|
local res = source >> shift;
|
|
$(Z) = (res == 0);
|
|
$(N) = 0;
|
|
$(V) = 0;
|
|
lreg = res;
|
|
stickyFlagL(source, shift);
|
|
}
|
|
|
|
:SJMP jmpdest11 is op16=0x4 & jmpdest11 {
|
|
goto jmpdest11;
|
|
}
|
|
|
|
:SKIP is op8=0x00 {
|
|
local tmp:1 = 0;
|
|
tmp = tmp; # avoid warning
|
|
} #2-byte NOP
|
|
|
|
:ST wreg, oper16 is op6=0x30 ... & oper16; wreg {
|
|
oper16 = wreg;
|
|
}
|
|
|
|
:STB breg, oper8 is op6=0x31 ... & oper8; breg {
|
|
oper8 = breg;
|
|
}
|
|
|
|
# 2-op
|
|
:SUB wreg, oper16 is op6=0x1a ... & oper16; wreg {
|
|
local tmp = wreg - oper16;
|
|
subtractFlags(wreg, oper16, tmp);
|
|
wreg = tmp;
|
|
}
|
|
|
|
# 3 op
|
|
:SUB dwreg, wreg, oper16 is op6=0x12 ... & oper16; wreg; dwreg {
|
|
dwreg = wreg - oper16;
|
|
subtractFlags(wreg, oper16, dwreg);
|
|
}
|
|
|
|
# 2-op
|
|
:SUBB breg, oper8 is op6=0x1e ... & oper8; breg {
|
|
local tmp = breg - oper8;
|
|
subtractFlags(breg, oper8, tmp);
|
|
}
|
|
|
|
:SUBB dbreg, breg, oper8 is op6=0x16 ... & oper8; breg; dbreg {
|
|
dbreg = breg - oper8;
|
|
subtractFlags(breg, oper8, dbreg);
|
|
}
|
|
|
|
:SUBC wreg, oper16 is op6=0x2a ... & oper16; wreg {
|
|
local tmp = wreg - oper16 - zext(1 - $(C));
|
|
local oldz = $(Z);
|
|
subtractFlags(wreg, oper16-zext(1-$(C)), tmp);
|
|
wreg = tmp;
|
|
$(Z) = oldz & $(Z);
|
|
}
|
|
|
|
:SUBCB breg, oper8 is op6=0x2e ... & oper8; breg {
|
|
local tmp = breg - oper8 - zext(1 - $(C));
|
|
local oldz = $(Z);
|
|
subtractFlags(breg, oper8-zext(1-$(C)), tmp);
|
|
breg = tmp;
|
|
$(Z) = oldz & $(Z);
|
|
}
|
|
|
|
@if defined(C196KC)
|
|
:TIJMP dwreg, "["wreg"]" "#"immed8 is op8=0xe2; wreg; immed8; dwreg {
|
|
local index = *wreg;
|
|
local jmpOffset = zext(index & immed8);
|
|
local tBase = dwreg;
|
|
local destX = (jmpOffset << 1) + tBase;
|
|
local jmpDest = *:2 destX;
|
|
|
|
goto [jmpDest];
|
|
}
|
|
|
|
@endif
|
|
|
|
:TRAP is op8=0xf7 {
|
|
ret:2 = inst_next;
|
|
push(ret);
|
|
trapv:2 = 0x2010;
|
|
PC = *trapv;
|
|
goto [PC];
|
|
}
|
|
|
|
:XOR wreg, oper16 is op6=0x21 ... & oper16; wreg {
|
|
tmpD:2 = wreg;
|
|
tmpS:2 = oper16;
|
|
tmpD = tmpD ^ tmpS;
|
|
wreg = tmpD;
|
|
resultFlags(wreg);
|
|
}
|
|
|
|
@if defined(C196KC)
|
|
:XCH wreg, waop16 is op8=0x04; waop16; wreg {
|
|
local tmp = wreg;
|
|
wreg = waop16;
|
|
waop16 = tmp;
|
|
}
|
|
|
|
:XCH wreg, immed8", TABLE["iwreg"]" is op8=0x0b; iwreg & addbit8=0; immed8; wreg {
|
|
local tmp = iwreg;
|
|
tmp = tmp + sext(immed8);
|
|
local val = *[RAM]:2 tmp;
|
|
|
|
local wreg_tmp = wreg;
|
|
wreg = val;
|
|
*[RAM]:2 tmp = wreg_tmp;
|
|
}
|
|
|
|
:XCH wreg, immed16", TABLE["iwreg"]" is op8=0x0b; iwreg & addbit8=1; immed16; wreg {
|
|
local tmp = iwreg;
|
|
tmp = tmp + immed16;
|
|
local val = *[RAM]:2 tmp;
|
|
|
|
local wreg_tmp = wreg;
|
|
wreg = val;
|
|
*[RAM]:2 tmp = wreg_tmp;
|
|
}
|
|
|
|
@endif
|
|
|
|
@if defined(C196KC)
|
|
:XCHB breg, baop8 is op8=0x14 ; baop8; breg {
|
|
local tmp = breg;
|
|
breg = baop8;
|
|
baop8 = tmp;
|
|
}
|
|
|
|
:XCHB breg, immed8", TABLE["iwreg"]" is op8=0x1b ; iwreg & addbit8=0; immed8; breg {
|
|
local tmp = iwreg;
|
|
tmp = tmp + sext(immed8);
|
|
local val = *[RAM]:1 tmp;
|
|
|
|
local wreg_tmp = breg;
|
|
breg = val;
|
|
*[RAM]:1 tmp = wreg_tmp;
|
|
}
|
|
|
|
:XCHB breg, immed16", TABLE["iwreg"]" is op8=0x1b ; iwreg & addbit8=1; immed16; breg {
|
|
local tmp = iwreg;
|
|
tmp = tmp + sext(immed16);
|
|
local val = *[RAM]:1 tmp;
|
|
|
|
local wreg_tmp = breg;
|
|
breg = val;
|
|
*[RAM]:1 tmp = wreg_tmp;
|
|
}
|
|
|
|
@endif
|
|
|
|
:XORB breg, oper8 is op6=0x25 ... & oper8; breg {
|
|
tmpD:1 = breg;
|
|
tmpS:1 = oper8;
|
|
tmpD = tmpD ^ tmpS;
|
|
breg = tmpD;
|
|
resultFlags(breg);
|
|
}
|
|
|
|
|
|
|