197 lines
5.8 KiB
C++
197 lines
5.8 KiB
C++
|
|
if ~ defined MPX
|
|
|
|
restore MPX ; this ensures that symbol cannot be forward-referenced
|
|
MPX = 1
|
|
|
|
element MPX.bnd
|
|
|
|
repeat 4, i:0
|
|
element bnd#i? : MPX.bnd + i
|
|
end repeat
|
|
|
|
macro MPX.parse_operand ns,op
|
|
x86.parse_operand#ns op
|
|
if ns.type = 'imm' & ns.size = 0 & ns.imm eq 1 elementof ns.imm & 1 metadataof ns.imm relativeto MPX.bnd
|
|
ns.type = 'bnd'
|
|
ns.mod = 11b
|
|
ns.rm = 1 metadataof ns.imm - MPX.bnd
|
|
ns.size = 0
|
|
end if
|
|
end macro
|
|
|
|
macro MPX.parse_sib_operand ns,op&
|
|
match [b=,si], op
|
|
ns.split = 1
|
|
ns.segment_prefix = 0
|
|
ns.prefix = 0
|
|
ns.opcode_prefix = 0
|
|
ns.rex_prefix = 0
|
|
ns.size = 0
|
|
ns.type = 'mem'
|
|
ns.base_part = +b
|
|
ns.index_part = +si
|
|
if x86.mode = 64
|
|
ns.mode = 64
|
|
ns.address_registers_type = x86.r64
|
|
else
|
|
ns.mode = 32
|
|
ns.address_registers_type = x86.r32
|
|
end if
|
|
ns.base_registers = 0
|
|
ns.index_registers = 0
|
|
repeat elementsof ns.base_part
|
|
if % metadataof ns.base_part relativeto x86.r16 | % metadataof ns.base_part relativeto x86.r32 | % metadataof ns.base_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip
|
|
ns.base_registers = ns.base_registers + % elementof ns.base_part * % scaleof ns.base_part
|
|
end if
|
|
end repeat
|
|
repeat elementsof ns.index_part
|
|
if % metadataof ns.index_part relativeto x86.r16 | % metadataof ns.index_part relativeto x86.r32 | % metadataof ns.index_part relativeto x86.r64 | % metadataof ns.address relativeto x86.ip
|
|
ns.index_registers = ns.index_registers + % elementof ns.index_part * % scaleof ns.index_part
|
|
end if
|
|
end repeat
|
|
ns.displacement = ns.base_part - ns.base_registers + ns.index_part - ns.index_registers
|
|
if ns.index_registers eq 0
|
|
ns.index = 4
|
|
ns.scale = 1
|
|
else if elementsof ns.index_registers = 1 & 1 metadataof ns.index_registers relativeto ns.address_registers_type & 1 metadataof ns.index_registers - ns.address_registers_type <> 4
|
|
ns.index = 1 metadataof ns.index_registers - ns.address_registers_type
|
|
ns.scale = 1 scaleof ns.index_registers
|
|
else
|
|
err 'invalid address'
|
|
end if
|
|
if ns.base_registers eq 0
|
|
ns.rm = 4
|
|
ns.base = 5
|
|
ns.index_only = 1
|
|
else if ns.base_registers eq 1 elementof ns.base_registers & 1 metadataof ns.base_registers relativeto ns.address_registers_type
|
|
ns.base = 1 metadataof ns.base_registers - ns.address_registers_type
|
|
if ns.index = 4 & ns.base <> 4
|
|
ns.rm = ns.base
|
|
else
|
|
ns.rm = 4
|
|
end if
|
|
ns.index_only = 0
|
|
else
|
|
err 'invalid address'
|
|
end if
|
|
ns.auto_relative = 0
|
|
ns.displacement_size = 4
|
|
ns.mod = 2
|
|
if ns.index_only
|
|
ns.mod = 0
|
|
else if ns.displacement relativeto 0
|
|
if ns.displacement = 0 & ns.rm and 111b <> 5 & (ns.rm <> 4 | ns.base and 111b <> 5)
|
|
ns.displacement_size = 0
|
|
ns.mod = 0
|
|
else if ns.displacement < 80h & ns.displacement >= -80h
|
|
ns.displacement_size = 1
|
|
ns.mod = 1
|
|
else if ns.displacement - 1 shl ns.mode >= -80h & ns.displacement < 1 shl ns.mode
|
|
ns.displacement = ns.displacement - 1 shl ns.mode
|
|
ns.displacement_size = 1
|
|
ns.mod = 1
|
|
end if
|
|
end if
|
|
else
|
|
ns.split = 0
|
|
x86.parse_operand#ns op
|
|
end match
|
|
end macro
|
|
|
|
macro bndmk? dest*,src*&
|
|
MPX.parse_operand @dest,dest
|
|
MPX.parse_sib_operand @src,src
|
|
if @dest.type = 'bnd' & @src.type = 'mem'
|
|
if @src.split & ~ 0 scaleof @src.base_part eq 0
|
|
err 'invalid base address'
|
|
end if
|
|
if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4)
|
|
err 'invalid operand size'
|
|
end if
|
|
@src.opcode_prefix = 0F3h
|
|
x86.store_instruction@src <0Fh,1Bh>,@dest.rm
|
|
else
|
|
err 'invalid combination of operands'
|
|
end if
|
|
end macro
|
|
|
|
macro bndmov? dest*,src*
|
|
MPX.parse_operand @dest,dest
|
|
MPX.parse_operand @src,src
|
|
if @dest.type = 'bnd' & (@src.type = 'bnd' | @src.type = 'mem')
|
|
if (x86.mode = 64 & @src.size and not 16) | (x86.mode < 64 & @src.size and not 8)
|
|
err 'invalid operand size'
|
|
end if
|
|
if @src.type = 'mem' & @src.mode <> x86.mode
|
|
err 'invalid address'
|
|
end if
|
|
@src.opcode_prefix = 66h
|
|
x86.store_instruction@src <0Fh,1Ah>,@dest.rm
|
|
else if @dest.type = 'mem' & @src.type = 'bnd'
|
|
if (x86.mode = 64 & @dest.size and not 16) | (x86.mode < 64 & @dest.size and not 8)
|
|
err 'invalid operand size'
|
|
end if
|
|
if @dest.type = 'mem' & @dest.mode <> x86.mode
|
|
err 'invalid address'
|
|
end if
|
|
@dest.opcode_prefix = 66h
|
|
x86.store_instruction@dest <0Fh,1Bh>,@src.rm
|
|
else
|
|
err 'invalid combination of operands'
|
|
end if
|
|
end macro
|
|
|
|
iterate <instr,prefix,ext>, bndcl,0F3h,1Ah, bndcu,0F2h,1Ah, bndcn,0F2h,1Bh
|
|
|
|
macro instr? dest*,src*
|
|
MPX.parse_operand @dest,dest
|
|
x86.parse_operand @src,src
|
|
if @dest.type = 'bnd' & (@src.type = 'reg' | @src.type = 'mem')
|
|
if (x86.mode = 64 & @src.size and not 8) | (x86.mode < 64 & @src.size and not 4)
|
|
err 'invalid operand size'
|
|
end if
|
|
if @src.type = 'mem' & @src.mode <> x86.mode
|
|
err 'invalid address'
|
|
end if
|
|
@src.opcode_prefix = prefix
|
|
x86.store_instruction@src <0Fh,ext>,@dest.rm
|
|
else
|
|
err 'invalid operand'
|
|
end if
|
|
end macro
|
|
|
|
end iterate
|
|
|
|
macro bndldx? dest*,src*&
|
|
MPX.parse_operand @dest,dest
|
|
MPX.parse_sib_operand @src,src
|
|
if @dest.type = 'bnd' & @src.type = 'mem'
|
|
if @src.scale > 1 | ( @src.split & ~ 0 scaleof @src.index_part eq 0 )
|
|
err 'invalid index'
|
|
end if
|
|
x86.store_instruction@src <0Fh,1Ah>,@dest.rm
|
|
else
|
|
err 'invalid combination of operands'
|
|
end if
|
|
end macro
|
|
|
|
macro bndstx? operands*&
|
|
match [dest] =, src, operands
|
|
MPX.parse_sib_operand @dest,[dest]
|
|
MPX.parse_operand @src,src
|
|
if @dest.type = 'mem' & @src.type = 'bnd'
|
|
if @dest.scale > 1 | ( @dest.split & ~ 0 scaleof @dest.index_part eq 0 )
|
|
err 'invalid index'
|
|
end if
|
|
x86.store_instruction@dest <0Fh,1Bh>,@src.rm
|
|
else
|
|
err 'invalid combination of operands'
|
|
end if
|
|
else
|
|
err 'invalid combination of operands'
|
|
end match
|
|
end macro
|
|
|
|
end if
|