862 lines
15 KiB
PHP
862 lines
15 KiB
PHP
|
|
; This is a very basic implementation of 8051 instruction set, which treats
|
|
; all types of addresses as plain numeric values and therefore is not able to
|
|
; detect whether symbol has been used in context it was not intended for.
|
|
|
|
element R
|
|
|
|
repeat 8 i:0
|
|
element R#i? : R + i
|
|
end repeat
|
|
|
|
element @
|
|
|
|
element @R0? : @
|
|
element @R1? : @ + 1
|
|
|
|
macro AJMP? addr
|
|
local value
|
|
value = +addr
|
|
if value and not 7FFh = ($+2) and not 7FFh
|
|
db 01h + value shr 3 and 11100000b,value and 0FFh
|
|
else
|
|
err "address out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro ACALL? addr
|
|
local value
|
|
value = +addr
|
|
if value and not 7FFh = ($+2) and not 7FFh
|
|
db 11h + value shr 3 and 11100000b,value and 0FFh
|
|
else
|
|
err "address out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro LCALL? addr
|
|
local value
|
|
value = +addr
|
|
db 12h,value shr 8,value and 0FFh
|
|
end macro
|
|
|
|
macro LJMP? addr
|
|
local value
|
|
value = +addr
|
|
db 02h,value shr 8,value and 0FFh
|
|
end macro
|
|
|
|
macro SJMP? addr
|
|
local offset
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 80h,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro CALL? addr
|
|
local value
|
|
value = +addr
|
|
if value and not 7FFh = ($+2) and not 7FFh
|
|
db 11h + value shr 3 and 11100000b
|
|
else
|
|
db 12h,value shr 8
|
|
end if
|
|
db value and 0FFh
|
|
end macro
|
|
|
|
macro JMP? addr
|
|
local value,offset
|
|
match =@A? + =DPTR?, addr
|
|
db 73h
|
|
else
|
|
value = +addr
|
|
offset = value-($+2)
|
|
if offset>=-80h & offset<80h
|
|
db 80h,offset
|
|
else
|
|
if value and not 7FFh = ($+2) and not 7FFh
|
|
db 01h + value shr 3 and 11100000b
|
|
else
|
|
db 02h,value shr 8
|
|
end if
|
|
db value and 0FFh
|
|
end if
|
|
end match
|
|
end macro
|
|
|
|
macro CJNE? operand1,operand2,addr
|
|
local value,offset
|
|
offset = -($+3)+addr
|
|
if offset>=-80h & offset<80h
|
|
match =A?, operand1
|
|
match #data, operand2
|
|
value = +data
|
|
db 0B4h,value
|
|
else
|
|
value = +operand2
|
|
db 0B5h,value
|
|
end match
|
|
else match #data,operand2
|
|
value = +operand1
|
|
if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 0B6h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 0B8h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
db +data
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
db offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro DJNZ? operand,addr
|
|
local value,offset
|
|
value = +operand
|
|
if value relativeto 0
|
|
offset = -($+3)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 0D5h,value,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
else if value eq value element 1 & value metadata 1 relativeto R
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 0D8h + value metadata 1 - R,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end macro
|
|
|
|
macro JBC? operand,addr
|
|
local offset
|
|
offset = -($+3)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 10h,operand,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JB? operand,addr
|
|
local offset
|
|
offset = -($+3)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 20h,operand,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JNB? operand,addr
|
|
local offset
|
|
offset = -($+3)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 30h,operand,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JC? addr
|
|
local offset
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 40h,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JNC? addr
|
|
local offset
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 50h,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JZ? addr
|
|
local offset
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 60h,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro JNZ? addr
|
|
local offset
|
|
offset = -($+2)+addr
|
|
if offset>=-80h & offset<80h
|
|
db 70h,offset
|
|
else
|
|
err "relative jump out of range"
|
|
end if
|
|
end macro
|
|
|
|
macro ADD? accu,operand
|
|
local value
|
|
match =A?, accu
|
|
match #data, operand
|
|
value = +data
|
|
db 24h,value
|
|
else
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 25h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 26h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 28h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro ADDC? accu,operand
|
|
local value
|
|
match =A?, accu
|
|
match #data, operand
|
|
value = +data
|
|
db 34h,value
|
|
else
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 35h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 36h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 38h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro SUBB? accu,operand
|
|
local value
|
|
match =A?, accu
|
|
match #data, operand
|
|
value = +data
|
|
db 94h,value
|
|
else
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 95h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 96h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 98h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro ANL? dest,src
|
|
local value,data_value
|
|
match =A?, dest
|
|
match #data, src
|
|
value = +data
|
|
db 54h,value
|
|
else
|
|
value = +src
|
|
if value relativeto 0
|
|
db 55h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 56h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 58h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else match =C?, dest
|
|
match /addr,src
|
|
db 0B0h,addr
|
|
else
|
|
db 82h,src
|
|
end match
|
|
else
|
|
match =A?, src
|
|
value = +dest
|
|
db 52h,value
|
|
else match #data, src
|
|
value = +dest
|
|
data_value = +data
|
|
db 53h,value,data_value
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end match
|
|
end macro
|
|
|
|
macro ORL? dest,src
|
|
local value,data_value
|
|
match =A?, dest
|
|
match #data, src
|
|
value = +data
|
|
db 44h,value
|
|
else
|
|
value = +src
|
|
if value relativeto 0
|
|
db 45h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 46h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 48h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else match =C?, dest
|
|
match /addr,src
|
|
db 0A0h,addr
|
|
else
|
|
db 72h,src
|
|
end match
|
|
else
|
|
match =A?, src
|
|
value = +dest
|
|
db 42h,value
|
|
else match #data, src
|
|
value = +dest
|
|
data_value = +data
|
|
db 43h,value,data_value
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end match
|
|
end macro
|
|
|
|
macro XRL? dest,src
|
|
local value,data_value
|
|
match =A?, dest
|
|
match #data, src
|
|
value = +data
|
|
db 64h,value
|
|
else
|
|
value = +src
|
|
if value relativeto 0
|
|
db 65h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 66h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 68h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else
|
|
match =A?, src
|
|
value = +dest
|
|
db 62h,value
|
|
else match #data, src
|
|
value = +dest
|
|
data_value = +data
|
|
db 63h,value,data_value
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end match
|
|
end macro
|
|
|
|
macro CLR? operand
|
|
match =A?, operand
|
|
db 0E4h
|
|
else match =C?, operand
|
|
db 0C3h
|
|
else
|
|
db 0C2h,operand
|
|
end match
|
|
end macro
|
|
|
|
macro CPL? operand
|
|
match =A?, operand
|
|
db 0F4h
|
|
else match =C?, operand
|
|
db 0B3h
|
|
else
|
|
db 0B2h,operand
|
|
end match
|
|
end macro
|
|
|
|
macro SETB? operand
|
|
match =C?, operand
|
|
db 0D3h
|
|
else
|
|
db 0D2h,operand
|
|
end match
|
|
end macro
|
|
|
|
macro DEC? operand
|
|
local value
|
|
match =A?, operand
|
|
db 14h
|
|
else
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 15h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 16h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 18h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
end macro
|
|
|
|
macro INC? operand
|
|
local value
|
|
match =A?, operand
|
|
db 04h
|
|
else match =DPTR?, operand
|
|
db 0A3h
|
|
else
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 05h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 06h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 08h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
end macro
|
|
|
|
macro MOV? dest,src
|
|
local value,data_value
|
|
match =A?, dest
|
|
match #data, src
|
|
value = +data
|
|
db 74h,value
|
|
else
|
|
value = +src
|
|
if value relativeto 0
|
|
db 0E5h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 0E6h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 0E8h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else match =C?, dest
|
|
db 0A2h,src
|
|
else match =C?, src
|
|
db 92h,dest
|
|
else match =DPTR?, dest
|
|
value = src
|
|
db 90h
|
|
if value eqtype ''
|
|
dw +src
|
|
else
|
|
db value shr 8,value and 0FFh
|
|
end if
|
|
else
|
|
value = +dest
|
|
if value relativeto 0
|
|
match =A?, src
|
|
db 0F5h,value
|
|
else match #data, src
|
|
data_value = +data
|
|
db 75h,value,data_value
|
|
else
|
|
@value2 = +src
|
|
if @value2 relativeto 0
|
|
db 85h,@value2,value
|
|
else if @value2 eq @value2 element 1
|
|
if @value2 metadata 1 relativeto @
|
|
db 86h + @value2 metadata 1 - @,value
|
|
else if @value2 metadata 1 relativeto R
|
|
db 88h + @value2 metadata 1 - R,value
|
|
end if
|
|
else if
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
match =A?, src
|
|
db 0F6h + value metadata 1 - @
|
|
else match #data, src
|
|
data_value = +data
|
|
db 76h + value metadata 1 - @,data_value
|
|
else
|
|
data_value = +src
|
|
db 0A6h + value metadata 1 - @,data_value
|
|
end match
|
|
else if value metadata 1 relativeto R
|
|
match =A?, src
|
|
db 0F8h + value metadata 1 - R
|
|
else match #data, src
|
|
data_value = +data
|
|
db 78h + value metadata 1 - R,data_value
|
|
else
|
|
data_value = +src
|
|
db 0A8h + value metadata 1 - R,data_value
|
|
end match
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
end macro
|
|
|
|
macro MOVC? operands&
|
|
match =A?=, =@A? + =DPTR?, operands
|
|
db 93h
|
|
else match =A?=, =@A? + =PC?, operands
|
|
db 83h
|
|
else
|
|
err "invalid operand"
|
|
end match
|
|
end macro
|
|
|
|
macro MOVX? dest,src
|
|
local value
|
|
match =A?, dest
|
|
match =@DPTR?, src
|
|
db 0E0h
|
|
else
|
|
value = +src
|
|
if value eq value element 1 & value metadata 1 relativeto @
|
|
db 0E2h + value metadata 1 - @
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else match =A?, src
|
|
match =@DPTR?, dest
|
|
db 0F0h
|
|
else
|
|
value = +dest
|
|
if value eq value element 1 & value metadata 1 relativeto @
|
|
db 0F2h + value metadata 1 - @
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
end match
|
|
else
|
|
err "invalid operand"
|
|
end match
|
|
end macro
|
|
|
|
macro SWAP? operand
|
|
match =A?, operand
|
|
db 0C4h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro DA? operand
|
|
match =A?, operand
|
|
db 0D4h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro RR? operand
|
|
match =A?, operand
|
|
db 03h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro RRC? operand
|
|
match =A?, operand
|
|
db 13h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro RL? operand
|
|
match =A?, operand
|
|
db 23h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro RLC? operand
|
|
match =A?, operand
|
|
db 33h
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro DIV? operand
|
|
match =AB?, operand
|
|
db 84h
|
|
else
|
|
err "invalid operand"
|
|
end match
|
|
end macro
|
|
|
|
macro MUL? operand
|
|
match =AB?, operand
|
|
db 0A4h
|
|
else
|
|
err "invalid operand"
|
|
end match
|
|
end macro
|
|
|
|
macro NOP?
|
|
db 0
|
|
end macro
|
|
|
|
macro POP? addr
|
|
local value
|
|
value = +addr
|
|
db 0D0h,value
|
|
end macro
|
|
|
|
macro PUSH? addr
|
|
local value
|
|
value = +addr
|
|
db 0C0h,value
|
|
end macro
|
|
|
|
macro RET?
|
|
db 22h
|
|
end macro
|
|
|
|
macro RETI?
|
|
db 32h
|
|
end macro
|
|
|
|
macro XCH? accu,operand
|
|
local value
|
|
match =A?, accu
|
|
value = +operand
|
|
if value relativeto 0
|
|
db 0C5h,value
|
|
else if value eq value element 1
|
|
if value metadata 1 relativeto @
|
|
db 0C6h + value metadata 1 - @
|
|
else if value metadata 1 relativeto R
|
|
db 0C8h + value metadata 1 - R
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err 'invalid operand'
|
|
end match
|
|
end macro
|
|
|
|
macro XCHD? accu,src
|
|
local value
|
|
match =A?, accu
|
|
value = +src
|
|
if value eq value element 1 & value metadata 1 relativeto @
|
|
db 0D6h + value metadata 1 - @
|
|
else
|
|
err "invalid operand"
|
|
end if
|
|
else
|
|
err "invalid operand"
|
|
end match
|
|
end macro
|
|
|
|
struc EQU? value
|
|
. = value
|
|
end struc
|
|
|
|
DSEG?.$ = 0
|
|
DSEG?.open = 0
|
|
|
|
macro DSEG? @:at DSEG?.$
|
|
if ~ DSEG?.open
|
|
virtual @
|
|
DSEG?.open = 1
|
|
else
|
|
match =AT? addr, @
|
|
org addr
|
|
else
|
|
err 'invalid argument'
|
|
end match
|
|
end if
|
|
end macro
|
|
|
|
macro CSEG? @
|
|
if DSEG?.open
|
|
DSEG?.$ = $
|
|
end virtual
|
|
DSEG?.open = 0
|
|
end if
|
|
match =AT? addr, @
|
|
org addr
|
|
else match any, @
|
|
err 'invalid argument'
|
|
end match
|
|
end macro
|
|
|
|
macro bitslabel definition
|
|
match name =at? address, definition
|
|
label name at address
|
|
repeat 8, i:0
|
|
label name.i at address+i
|
|
end repeat
|
|
else
|
|
err 'syntax error'
|
|
end match
|
|
end macro
|
|
|
|
; Data addresses:
|
|
|
|
bitslabel P0 at 080h
|
|
bitslabel SP at 081h
|
|
bitslabel DPL at 082h
|
|
bitslabel DPH at 083h
|
|
bitslabel PCON at 087h
|
|
bitslabel TCON at 088h
|
|
bitslabel TMOD at 089h
|
|
bitslabel TL0 at 08Ah
|
|
bitslabel TL1 at 08Bh
|
|
bitslabel TH0 at 08Ch
|
|
bitslabel TH1 at 08Dh
|
|
bitslabel P1 at 090h
|
|
bitslabel SCON at 098h
|
|
bitslabel SBUF at 099h
|
|
bitslabel P2 at 0A0h
|
|
bitslabel IE at 0A8h
|
|
bitslabel P3 at 0B0h
|
|
bitslabel IP at 0B8h
|
|
bitslabel PSW at 0D0h
|
|
bitslabel ACC at 0E0h
|
|
bitslabel B at 0F0h
|
|
|
|
; Bit addresses:
|
|
|
|
label IT0 at 088h
|
|
label IE0 at 089h
|
|
label IT1 at 08Ah
|
|
label IE1 at 08Bh
|
|
label TR0 at 08Ch
|
|
label TF0 at 08Dh
|
|
label TR1 at 08Eh
|
|
label TF1 at 08Fh
|
|
label RI at 098h
|
|
label TI at 099h
|
|
label RB8 at 09Ah
|
|
label TB8 at 09Bh
|
|
label REN at 09Ch
|
|
label SM2 at 09Dh
|
|
label SM1 at 09Eh
|
|
label SM0 at 09Fh
|
|
label EX0 at 0A8h
|
|
label ET0 at 0A9h
|
|
label EX1 at 0AAh
|
|
label ET1 at 0ABh
|
|
label ES at 0ACh
|
|
label EA at 0AFh
|
|
label RXD at 0B0h
|
|
label TXD at 0B1h
|
|
label INT0 at 0B2h
|
|
label INT1 at 0B3h
|
|
label T0 at 0B4h
|
|
label T1 at 0B5h
|
|
label WR at 0B6h
|
|
label RD at 0B7h
|
|
label PX0 at 0B8h
|
|
label PT0 at 0B9h
|
|
label PX1 at 0BAh
|
|
label PT1 at 0BBh
|
|
label PS at 0BCh
|
|
label P at 0D0h
|
|
label OV at 0D2h
|
|
label RS0 at 0D3h
|
|
label RS1 at 0D4h
|
|
label F0 at 0D5h
|
|
label AC at 0D6h
|
|
label CY at 0D7h
|
|
|
|
; Code addresses:
|
|
|
|
label RESET at 000h
|
|
label EXTI0 at 003h
|
|
label TIMER0 at 00Bh
|
|
label EXTI1 at 013h
|
|
label TIMER1 at 01Bh
|
|
label SINT at 023h
|