Generate Intel encoding recipes on demand.
Cretonne's encoding recipes need to have a fixed size so we can compute accurate branch destination addresses. Intel's instruction encoding has a lot of variance in the number of bytes needed to encode the opcode which leads to a number of duplicated encoding recipes that only differ in the opcode size. Add an Intel-specific TailEnc Python class which represents an abstraction over a set of recipes that are identical except for the opcode encoding. The TailEnc can then generate specific encoding recipes for each opcode format. The opcode format is a prefix of the recipe name, so for example, the 'rr' TailEnc will generate the 'Op1rr', 'Op2rr', 'Mp2rr' etc recipes. The TailEnc class provides a __call__ implementation that simply takes the sequence of opcode bytes as arguments. It then looks up the right prefix for the opcode bytes.
This commit is contained in:
@@ -4,61 +4,60 @@ Intel Encodings.
|
||||
from __future__ import absolute_import
|
||||
from base import instructions as base
|
||||
from .defs import I32
|
||||
from . import recipes as rcp
|
||||
from .recipes import OP, OP0F, MP66
|
||||
from . import recipes as r
|
||||
|
||||
I32.enc(base.iadd.i32, rcp.Op1rr, OP(0x01))
|
||||
I32.enc(base.isub.i32, rcp.Op1rr, OP(0x29))
|
||||
I32.enc(base.iadd.i32, *r.rr(0x01))
|
||||
I32.enc(base.isub.i32, *r.rr(0x29))
|
||||
|
||||
I32.enc(base.band.i32, rcp.Op1rr, OP(0x21))
|
||||
I32.enc(base.bor.i32, rcp.Op1rr, OP(0x09))
|
||||
I32.enc(base.bxor.i32, rcp.Op1rr, OP(0x31))
|
||||
I32.enc(base.band.i32, *r.rr(0x21))
|
||||
I32.enc(base.bor.i32, *r.rr(0x09))
|
||||
I32.enc(base.bxor.i32, *r.rr(0x31))
|
||||
|
||||
# Immediate instructions with sign-extended 8-bit and 32-bit immediate.
|
||||
for inst, r in [
|
||||
for inst, rrr in [
|
||||
(base.iadd_imm.i32, 0),
|
||||
(base.band_imm.i32, 4),
|
||||
(base.bor_imm.i32, 1),
|
||||
(base.bxor_imm.i32, 6)]:
|
||||
I32.enc(inst, rcp.Op1rib, OP(0x83, rrr=r))
|
||||
I32.enc(inst, rcp.Op1rid, OP(0x81, rrr=r))
|
||||
I32.enc(inst, *r.rib(0x83, rrr=rrr))
|
||||
I32.enc(inst, *r.rid(0x81, rrr=rrr))
|
||||
|
||||
# 32-bit shifts and rotates.
|
||||
# Note that the dynamic shift amount is only masked by 5 or 6 bits; the 8-bit
|
||||
# and 16-bit shifts would need explicit masking.
|
||||
I32.enc(base.ishl.i32.i32, rcp.Op1rc, OP(0xd3, rrr=4))
|
||||
I32.enc(base.ushr.i32.i32, rcp.Op1rc, OP(0xd3, rrr=5))
|
||||
I32.enc(base.sshr.i32.i32, rcp.Op1rc, OP(0xd3, rrr=7))
|
||||
I32.enc(base.ishl.i32.i32, *r.rc(0xd3, rrr=4))
|
||||
I32.enc(base.ushr.i32.i32, *r.rc(0xd3, rrr=5))
|
||||
I32.enc(base.sshr.i32.i32, *r.rc(0xd3, rrr=7))
|
||||
|
||||
# Loads and stores.
|
||||
I32.enc(base.store.i32.i32, rcp.Op1st, OP(0x89))
|
||||
I32.enc(base.store.i32.i32, rcp.Op1stDisp8, OP(0x89))
|
||||
I32.enc(base.store.i32.i32, rcp.Op1stDisp32, OP(0x89))
|
||||
I32.enc(base.store.i32.i32, *r.st(0x89))
|
||||
I32.enc(base.store.i32.i32, *r.stDisp8(0x89))
|
||||
I32.enc(base.store.i32.i32, *r.stDisp32(0x89))
|
||||
|
||||
I32.enc(base.istore16.i32.i32, rcp.Mp1st, MP66(0x89))
|
||||
I32.enc(base.istore16.i32.i32, rcp.Mp1stDisp8, MP66(0x89))
|
||||
I32.enc(base.istore16.i32.i32, rcp.Mp1stDisp32, MP66(0x89))
|
||||
I32.enc(base.istore16.i32.i32, *r.st(0x66, 0x89))
|
||||
I32.enc(base.istore16.i32.i32, *r.stDisp8(0x66, 0x89))
|
||||
I32.enc(base.istore16.i32.i32, *r.stDisp32(0x66, 0x89))
|
||||
|
||||
I32.enc(base.istore8.i32.i32, rcp.Op1st_abcd, OP(0x88))
|
||||
I32.enc(base.istore8.i32.i32, rcp.Op1stDisp8_abcd, OP(0x88))
|
||||
I32.enc(base.istore8.i32.i32, rcp.Op1stDisp32_abcd, OP(0x88))
|
||||
I32.enc(base.istore8.i32.i32, *r.st_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.i32, *r.stDisp8_abcd(0x88))
|
||||
I32.enc(base.istore8.i32.i32, *r.stDisp32_abcd(0x88))
|
||||
|
||||
I32.enc(base.load.i32.i32, rcp.Op1ld, OP(0x8b))
|
||||
I32.enc(base.load.i32.i32, rcp.Op1ldDisp8, OP(0x8b))
|
||||
I32.enc(base.load.i32.i32, rcp.Op1ldDisp32, OP(0x8b))
|
||||
I32.enc(base.load.i32.i32, *r.ld(0x8b))
|
||||
I32.enc(base.load.i32.i32, *r.ldDisp8(0x8b))
|
||||
I32.enc(base.load.i32.i32, *r.ldDisp32(0x8b))
|
||||
|
||||
I32.enc(base.uload16.i32.i32, rcp.Op2ld, OP0F(0xb7))
|
||||
I32.enc(base.uload16.i32.i32, rcp.Op2ldDisp8, OP0F(0xb7))
|
||||
I32.enc(base.uload16.i32.i32, rcp.Op2ldDisp32, OP0F(0xb7))
|
||||
I32.enc(base.uload16.i32.i32, *r.ld(0x0f, 0xb7))
|
||||
I32.enc(base.uload16.i32.i32, *r.ldDisp8(0x0f, 0xb7))
|
||||
I32.enc(base.uload16.i32.i32, *r.ldDisp32(0x0f, 0xb7))
|
||||
|
||||
I32.enc(base.sload16.i32.i32, rcp.Op2ld, OP0F(0xbf))
|
||||
I32.enc(base.sload16.i32.i32, rcp.Op2ldDisp8, OP0F(0xbf))
|
||||
I32.enc(base.sload16.i32.i32, rcp.Op2ldDisp32, OP0F(0xbf))
|
||||
I32.enc(base.sload16.i32.i32, *r.ld(0x0f, 0xbf))
|
||||
I32.enc(base.sload16.i32.i32, *r.ldDisp8(0x0f, 0xbf))
|
||||
I32.enc(base.sload16.i32.i32, *r.ldDisp32(0x0f, 0xbf))
|
||||
|
||||
I32.enc(base.uload8.i32.i32, rcp.Op2ld, OP0F(0xb6))
|
||||
I32.enc(base.uload8.i32.i32, rcp.Op2ldDisp8, OP0F(0xb6))
|
||||
I32.enc(base.uload8.i32.i32, rcp.Op2ldDisp32, OP0F(0xb6))
|
||||
I32.enc(base.uload8.i32.i32, *r.ld(0x0f, 0xb6))
|
||||
I32.enc(base.uload8.i32.i32, *r.ldDisp8(0x0f, 0xb6))
|
||||
I32.enc(base.uload8.i32.i32, *r.ldDisp32(0x0f, 0xb6))
|
||||
|
||||
I32.enc(base.sload8.i32.i32, rcp.Op2ld, OP0F(0xbe))
|
||||
I32.enc(base.sload8.i32.i32, rcp.Op2ldDisp8, OP0F(0xbe))
|
||||
I32.enc(base.sload8.i32.i32, rcp.Op2ldDisp32, OP0F(0xbe))
|
||||
I32.enc(base.sload8.i32.i32, *r.ld(0x0f, 0xbe))
|
||||
I32.enc(base.sload8.i32.i32, *r.ldDisp8(0x0f, 0xbe))
|
||||
I32.enc(base.sload8.i32.i32, *r.ldDisp32(0x0f, 0xbe))
|
||||
|
||||
Reference in New Issue
Block a user