asm_dip/toolchain/fasmg.kl0e/examples/x86/include/80186.inc
2024-11-24 23:13:28 -05:00

384 lines
8.2 KiB
C++

include '8086.inc'
define @aux @aux
calminstruction push? src*
call x86.parse_operand@src, src
check @src.size and not 2
jno main
err 'invalid operand size'
main:
check @src.type = 'mem'
jyes push_mem
check @src.type = 'reg'
jyes push_reg
check @src.type = 'sreg'
jyes push_sreg
check @src.type = 'imm'
jyes push_imm
err 'invalid operand'
exit
push_mem:
xcall x86.store_instruction@src, (0FFh),(110b)
exit
push_reg:
emit 1, 50h + @src.rm
exit
push_sreg:
emit 1, 6 + @src.rm shl 3
exit
push_imm:
check @src.imm relativeto 0 & @src.imm < 80h & @src.imm >= -80h
jyes push_simm
check @src.imm relativeto 0 & @src.imm - 10000h >= -80h & @src.imm < 10000h
jyes push_simm_wrap
emit 1, 68h
asm dw @src.imm
exit
push_simm_wrap:
compute @src.imm, @src.imm - 10000h
push_simm:
emit 1, 6Ah
emit 1, @src.imm
exit
end calminstruction
calminstruction x86.pop_instruction size:0,dest*
call x86.parse_operand@dest, dest
check @dest.size and not 2
jno main
err 'invalid operand size'
main:
check @dest.type = 'mem'
jyes pop_mem
check @dest.type = 'reg'
jyes pop_reg
check @dest.type = 'sreg'
jyes pop_sreg
invalid_operand:
err 'invalid operand'
exit
pop_mem:
xcall x86.store_instruction@dest, (8Fh),(0)
exit
pop_reg:
emit 1, 58h + @dest.rm
exit
pop_sreg:
check @dest.rm = 1
jyes invalid_operand
emit 1, 7 + @dest.rm shl 3
exit
end calminstruction
iterate <instr>, push,pop
calminstruction instr? operand
local head, tail
match head tail, operand
jno plain
transform head, x86.compact
jno plain
match {head}, head
jno plain
loop:
arrange operand, =instr head
assemble operand
match head tail, tail
jno final
transform head, x86.compact
jno error
match {head}, head
jyes loop
error:
err 'only register operands allowed in compact syntax'
exit
final:
transform tail, x86.compact
jno error
match {operand}, tail
jno error
plain:
arrange operand, =instr operand
assemble operand
end calminstruction
end iterate
iterate <instr,opcode>, pusha,60h, popa,61h, insb,6Ch, outsb,6Eh, insw,6Dh, outsw,6Fh, leave,0C9h
calminstruction instr?
emit 1, opcode
end calminstruction
end iterate
calminstruction imul? dest*,src&
local size
call x86.parse_operand@dest, dest
match , src
jyes imul_rm
local src1, src2
match src1 =, src2, src
jyes imul_second_source
call x86.parse_operand@src, src
check @dest.size = 0 & @src.size = 0
jyes operand_size_not_specified
check @dest.size <> 0 & @src.size <> 0 & @dest.size <> @src.size
jyes operand_sizes_do_not_match
compute size, @dest.size or @src.size
check @src.type = 'imm' & @dest.type = 'reg'
jno invalid_combination_of_operands
compute @aux.type, @src.type
compute @aux.imm, @src.imm
compute @src.type, @dest.type
compute @src.mod, @dest.mod
compute @src.rm, @dest.rm
jump main
imul_second_source:
call x86.parse_operand@src, src1
call x86.parse_operand@aux, src2
check @dest.size = 0 & @src.size = 0 & @aux.size = 0
jyes operand_size_not_specified
compute size, @dest.size or @src.size or @aux.size
check (@dest.size & @dest.size <> size) | (@src.size & @src.size <> size) | (@aux.size & @aux.size <> size)
jyes operand_sizes_do_not_match
jump main
operand_size_not_specified:
err 'operand size not specified'
compute size, 0
jump main
operand_sizes_do_not_match:
err 'operand sizes do not match'
compute size, 0
jump main
main:
check @aux.type = 'imm' & ( @src.type = 'mem' | @src.type = 'reg' ) & @dest.type = 'reg' & size = 2
jyes imul_reg_rm_imm
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
imul_rm:
check @dest.size
jyes imul_rm_size_ok
err 'operand size not specified'
imul_rm_size_ok:
check @dest.type = 'mem' | @dest.type = 'reg'
jno invalid_combination_of_operands
check @dest.size < 2
jyes imul_rm_8bit
xcall x86.store_instruction@dest, (0F7h),(5)
exit
imul_rm_8bit:
xcall x86.store_instruction@dest, (0F6h),(5)
exit
imul_reg_rm_imm:
check @aux.imm relativeto 0 & @aux.imm < 80h & @aux.imm >= -80h
jyes imul_reg_rm_simm
check @aux.imm relativeto 0 & @aux.imm - 10000h >= -80h & @aux.imm < 10000h
jyes imul_reg_rm_simm_wrap
xcall x86.store_instruction@src, (69h),@dest.rm,size,@aux.imm
exit
imul_reg_rm_simm_wrap:
compute @aux.imm, @aux.imm - 1 shl (size shl 3)
imul_reg_rm_simm:
xcall x86.store_instruction@src, (6Bh),@dest.rm,byte,@aux.imm
exit
end calminstruction
iterate <instr,postbyte>, rol,0, ror,1, rcl,2, rcr,3, shl,4, sal, 4, shr,5, sar,7
calminstruction instr? dest*,cnt*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, cnt
check @dest.size = 0
jyes operand_size_not_specified
check @src.size and not 1
jyes invalid_operand_size
main:
check @src.type = 'reg' & @src.size = 1 & @src.rm = 1 & ( @dest.type = 'reg' | @dest.type = 'mem' )
jyes shift_rm_cl
check @src.type = 'imm' & ( @dest.type = 'reg' | @dest.type = 'mem' )
jyes shift_rm_imm
err 'invalid combination of operands'
exit
shift_rm_cl:
check @dest.size < 2
jyes shift_r8_cl
xcall x86.store_instruction@dest, (0D3h),(postbyte)
exit
shift_r8_cl:
xcall x86.store_instruction@dest, (0D2h),(postbyte)
exit
shift_rm_imm:
check @dest.size < 2
jyes shift_rm8_imm
check @src.imm = 1
jyes shift_rm_1
xcall x86.store_instruction@dest, (0C1h),(postbyte),byte,@src.imm
exit
shift_rm_1:
xcall x86.store_instruction@dest, (0D1h),(postbyte)
exit
shift_rm8_imm:
check @src.imm = 1
jyes shift_rm8_1
xcall x86.store_instruction@dest, (0C0h),(postbyte),byte,@src.imm
exit
shift_rm8_1:
xcall x86.store_instruction@dest, (0D0h),(postbyte)
exit
operand_size_not_specified:
err 'operand size not specified'
jump main
invalid_operand_size:
err 'invalid operand size'
jump main
end calminstruction
end iterate
calminstruction ins? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @dest.size
jyes size_ok
err 'operand size not specified'
compute size, 0
size_ok:
check @src.type = 'reg' & @src.size = 2 & @src.rm = 2 & @dest.type = 'mem' & @dest.mod = 0 & @dest.rm = 5 & ( @dest.segment_prefix = 0 | @dest.segment_prefix = 26h )
jno invalid_combination_of_operands
check @dest.size = 2
jyes ins_word
assemble x86.insb
exit
ins_word:
assemble x86.insw
exit
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
end calminstruction
calminstruction outs? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.size
jyes size_ok
err 'operand size not specified'
size_ok:
check @dest.type = 'reg' & @dest.size = 2 & @dest.rm = 2 & @src.type = 'mem' & @src.mod = 0 & @src.rm = 4
jno invalid_combination_of_operands
check @src.segment_prefix = 0 | @src.segment_prefix = 3Eh
jyes segment_prefix_ok
emit 1, @src.segment_prefix
segment_prefix_ok:
check @src.size = 2
jyes outs_word
assemble x86.outsb
exit
outs_word:
assemble x86.outsw
exit
operand_size_not_specified:
err 'operand size not specified'
compute size, 0
jump size_ok
operand_sizes_do_not_match:
err 'operand sizes do not match'
compute size, 0
jump size_ok
invalid_combination_of_operands:
err 'invalid combination of operands'
exit
end calminstruction
calminstruction enter? alloc*,nesting*
call x86.parse_operand@src, alloc
call x86.parse_operand@aux, nesting
check (@src.size and not 2) | (@aux.size and not 1)
jno size_ok
err 'invalid operand size'
size_ok:
check @src.type = 'imm' & @aux.type = 'imm'
jno operand_ok
err 'invalid operand'
exit
operand_ok:
emit 1, 0C8h
asm dw @src.imm
emit 1, @aux.imm
end calminstruction
calminstruction bound? dest*,src*
call x86.parse_operand@dest, dest
call x86.parse_operand@src, src
check @src.type = 'mem' & @dest.type = 'reg'
jno invalid_combination_of_operands
check @dest.size = 2
jno invalid_operand_size
check @src.size and not @dest.size
jno size_ok
err 'operand sizes do not match'
size_ok:
xcall x86.store_instruction@src, (62h),@dest.rm
exit
invalid_operand_size:
err 'invalid operand size'
invalid_combination_of_operands:
err 'invalid combination of operands'
end calminstruction