# HG changeset patch
# User Windel Bouwman
# Date 1401358417 -7200
# Node ID c0d9837acde8867680f15f61abfd53da3631be89
# Parent 5d03c10fe19dc6393a992f9e7111f9ec2a0881f7
x86 target refactor
diff -r 5d03c10fe19d -r c0d9837acde8 kernel/arch/qemu_vexpress/layout.mmap
--- a/kernel/arch/qemu_vexpress/layout.mmap Thu May 29 10:47:28 2014 +0200
+++ b/kernel/arch/qemu_vexpress/layout.mmap Thu May 29 12:13:37 2014 +0200
@@ -4,6 +4,8 @@
SECTION(code)
ALIGN(0x4000)
SECTION(mem_tables)
+ ALIGN(0x4000)
+ SECTION(ramdisk)
}
MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
diff -r 5d03c10fe19d -r c0d9837acde8 kernel/build.xml
--- a/kernel/build.xml Thu May 29 10:47:28 2014 +0200
+++ b/kernel/build.xml Thu May 29 12:13:37 2014 +0200
@@ -11,6 +11,9 @@
+
+
@@ -23,7 +26,7 @@
+ objects="henkie.o;vexp.o;start.o;ramdisk.o" />
> (p*8)) & 0xFF for p in range(8) ]
+
+def imm32(x):
+ """ represent 32 bits integer in little endian 4 bytes"""
+ if x < 0:
+ x = x + (1 << 32)
+ x = x & 0xFFFFFFFF
+ return [ (x >> (p*8)) & 0xFF for p in range(4) ]
+
+
+def imm8(x):
+ if x < 0:
+ x = x + (1 << 8)
+ x = x & 0xFF
+ return [ x ]
+
+
+class ModRmToken(Token):
+ """ Construct the modrm byte from its components """
+ def __init__(self, mod=0, rm=0, reg=0):
+ super().__init__(8)
+ assert(mod <= 3)
+ assert(rm <= 7)
+ assert(reg <= 7)
+ self.mod = mod
+ self.rm = rm
+ self.reg = reg
+
+ mod = bit_range(6, 8)
+ rm = bit_range(0, 3)
+ reg = bit_range(3, 6)
+
+ def encode(self):
+ return u8(self.bit_value)
+
+
+class RexToken(Token):
+ """ Create a REX prefix byte """
+ def __init__(self, w=0, r=0, x=0, b=0):
+ super().__init__(8)
+ assert(w <= 1)
+ assert(r <= 1)
+ assert(x <= 1)
+ assert(b <= 1)
+ self.w = w
+ self.r = r
+ self.x = x
+ self.b = b
+ self.set_bit(6, 1)
+
+ w = bit_range(3, 4)
+ r = bit_range(2, 3)
+ x = bit_range(1, 2)
+ b = bit_range(0, 1)
+
+ def encode(self):
+ return u8(self.bit_value)
+
+
+def sib(ss=0, index=0, base=0):
+ assert(ss <= 3)
+ assert(index <= 7)
+ assert(base <= 7)
+ return (ss << 6) | (index << 3) | base
+
+tttn = {'L':0xc,'G':0xf,'NE':0x5,'GE':0xd,'LE':0xe, 'E':0x4}
+
+# Actual instructions:
+def nearjump(distance, condition=None):
+ """ jmp imm32 """
+ lim = (1<<30)
+ if abs(distance) > lim:
+ Error('near jump cannot jump over more than {0} bytes'.format(lim))
+ if condition:
+ if distance < 0:
+ distance -= 6 # Skip own instruction
+ opcode = 0x80 | tttn[condition] # Jcc imm32
+ return [0x0F, opcode] + imm32(distance)
+ else:
+ if distance < 0:
+ distance -= 5 # Skip own instruction
+ return [ 0xE9 ] + imm32(distance)
+
+def shortjump(distance, condition=None):
+ """ jmp imm8 """
+ lim = 118
+ if abs(distance) > lim:
+ Error('short jump cannot jump over more than {0} bytes'.format(lim))
+ if distance < 0:
+ distance -= 2 # Skip own instruction
+ if condition:
+ opcode = 0x70 | tttn[condition] # Jcc rel8
+ else:
+ opcode = 0xeb # jmp rel8
+ return [opcode] + imm8(distance)
+
+# Helper that determines jump type:
+def reljump(distance):
+ if abs(distance) < 110:
+ return shortjump(distance)
+ else:
+ return nearjump(distance)
+
+
+class Push(Instruction):
+ def __init__(self, reg):
+ assert(reg in regs64), str(reg)
+ self.reg = reg
+
+ def encode(self):
+ code = []
+ if self.reg.rexbit == 1:
+ code.append(0x41)
+ code.append(0x50 + self.reg.regbits)
+ return bytes(code)
+
+
+class Pop(Instruction):
+ def __init__(self, reg):
+ assert(reg in regs64), str(reg)
+ self.reg = reg
+
+ def encode(self):
+ code = []
+ if self.reg.rexbit == 1:
+ code.append(0x41)
+ code.append(0x58 + self.reg.regbits)
+ return bytes(code)
+
+
+def pop(reg):
+ if reg in regs64:
+ if rexbit[reg] == 1:
+ rexprefix = rex(b=1)
+ opcode = 0x58 + regs64[reg]
+ return [rexprefix, opcode]
+ else:
+ opcode = 0x58 + regs64[reg]
+ return [ opcode ]
+ else:
+ Error('pop for {0} not implemented'.format(reg))
+
+def INT(number):
+ opcode = 0xcd
+ return [opcode] + imm8(number)
+
+def syscall():
+ return [0x0F, 0x05]
+
+def call(distance):
+ if type(distance) is int:
+ return [0xe8]+imm32(distance)
+ elif type(distance) is str and distance in regs64:
+ reg = distance
+ opcode = 0xFF # 0xFF /2 == call r/m64
+ mod_rm = modrm(mod=3, reg=2, rm=regs64[reg])
+ if rexbit[reg] == 1:
+ rexprefix = rex(b=rexbit[reg])
+ return [rexprefix, opcode, mod_rm]
+ else:
+ return [opcode, mod_rm]
+ else:
+ Error('Cannot call to {0}'.format(distance))
+
+
+class Ret(Instruction):
+ def __init__(self):
+ pass
+
+ def encode(self):
+ return [ 0xc3 ]
+
+
+class Inc(Instruction):
+ def __init__(self, reg):
+ assert(reg in regs64), str(reg)
+ self.rex = RexToken(w=1, b=reg.rexbit)
+ self.opcode = 0xff
+ self.mod_rm = ModRmToken(mod=3, rm=reg.regbits)
+
+ def encode(self):
+ code = bytes([self.opcode])
+ return self.rex.encode() + code + self.mod_rm.encode()
+
+
+def prepost8(r8, rm8):
+ assert(r8 in regs8)
+ pre = []
+ if type(rm8) is list:
+ # TODO: merge mem access with prepost for 64 bits
+ if len(rm8) == 1:
+ base, = rm8
+ if type(base) is str and base in regs64:
+ assert(not base in ['rbp', 'rsp', 'r12', 'r13'])
+ mod_rm = modrm(mod=0, rm=regs64[base], reg=regs8[r8])
+ if rexbit[base] == 1:
+ pre.append(rex(b=1))
+ post = [mod_rm]
+ else:
+ Error('One arg of type {0} not implemented'.format(base))
+ elif len(rm8) == 2:
+ base, offset = rm8
+ assert(type(offset) is int)
+ assert(base in regs64)
+
+ if base == 'rsp' or base == 'r12':
+ Error('Cannot use rsp or r12 as base yet')
+ if rexbit[base] == 1:
+ pre.append( rex(b=1) )
+ mod_rm = modrm(mod=1, rm=regs64[base], reg=regs8[r8])
+ post = [mod_rm] + imm8(offset)
+ else:
+ Error('not supporting prepost8 with list len {0}'.format(len(rm8)))
+ else:
+ Error('Not supporting move with reg8 {0}'.format(r8))
+ return pre, post
+
+def prepost(r64, rm64):
+ assert(r64 in regs64)
+ if type(rm64) is list:
+ if len(rm64) == 3:
+ base, index, disp = rm64
+ assert(base in regs64)
+ assert(index in regs64)
+ assert(type(disp) is int)
+ # Assert that no special cases are used:
+ # TODO: swap base and index to avoid special cases
+ # TODO: exploit special cases and make better code
+ assert(index != 'rsp')
+
+ rexprefix = rex(w=1, r=rexbit[r64], x=rexbit[index], b=rexbit[base])
+ # mod=1 and rm=4 indicates a SIB byte: [--][--]+imm8
+ mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
+ si_b = sib(ss=0, index=regs64[index], base=regs64[base])
+ return [rexprefix], [mod_rm, si_b] + imm8(disp)
+ elif len(rm64) == 2:
+ base, offset = rm64
+ assert(type(offset) is int)
+ if base == 'RIP':
+ # RIP pointer relative addressing mode!
+ rexprefix = rex(w=1, r=rexbit[r64])
+ mod_rm = modrm(mod=0, rm=5, reg=regs64[r64])
+ return [rexprefix], [mod_rm] + imm32(offset)
+ else:
+ assert(base in regs64)
+
+ if base == 'rsp' or base == 'r12':
+ # extended function that uses SIB byte
+ rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
+ # rm=4 indicates a SIB byte follows
+ mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
+ # index=4 indicates that index is not used
+ si_b = sib(ss=0, index=4, base=regs64[base])
+ return [rexprefix], [mod_rm, si_b] + imm8(offset)
+ else:
+ rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
+ mod_rm = modrm(mod=1, rm=regs64[base], reg=regs64[r64])
+ return [rexprefix], [mod_rm] + imm8(offset)
+ elif len(rm64) == 1:
+ offset = rm64[0]
+ if type(offset) is int:
+ rexprefix = rex(w=1, r=rexbit[r64])
+ mod_rm = modrm(mod=0, rm=4,reg=regs64[r64])
+ si_b = sib(ss=0, index=4,base=5) # 0x25
+ return [rexprefix], [mod_rm, si_b] + imm32(offset)
+ else:
+ Error('Memory reference of type {0} not implemented'.format(offset))
+ else:
+ Error('Memory reference not implemented')
+ elif rm64 in regs64:
+ rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[rm64])
+ mod_rm = modrm(3, rm=regs64[rm64], reg=regs64[r64])
+ return [rexprefix], [mod_rm]
+
+
+def leareg64(rega, m):
+ opcode = 0x8d # lea r64, m
+ pre, post = prepost(rega, m)
+ return pre + [opcode] + post
+
+
+class Mov1(Instruction):
+ """ Mov r64 to r64 """
+ def __init__(self, dst, src):
+ assert src in regs64, str(src)
+ assert dst in regs64, str(dst)
+ self.rex = RexToken(w=1, r=dst.rexbit, b=src.rexbit)
+ self.mod_rm = ModRmToken(mod=3, rm=dst.regbits, reg=src.regbits)
+
+ def encode(self):
+ opcode = 0x89 # mov r/m64, r64
+ code = bytes([opcode])
+ return self.rex.encode() + code + self.mod_rm.encode()
+
+
+def Mov(dst, src):
+ if type(src) is int:
+ pre = [rex(w=1, b=rexbit[rega])]
+ opcode = 0xb8 + regs64[rega]
+ post = imm64(regb)
+ elif type(src) is X86Register:
+ return Mov1(dst, src)
+ elif type(src) is str:
+ if rega in regs64:
+ opcode = 0x8b # mov r64, r/m64
+ pre, post = prepost(rega, regb)
+ else:
+ raise Exception('Unknown register {0}'.format(rega))
+ else:
+ raise Exception('Move of this kind {0}, {1} not implemented'.format(rega, regb))
+ return pre + [opcode] + post
+
+
+def Xor(rega, regb):
+ return Xor1(rega, regb)
+
+
+class Xor1(Instruction):
+ def __init__(self, a, b):
+ self.rex = RexToken(w=1, r=b.rexbit, b=a.rexbit)
+ self.mod_rm = ModRmToken(mod=3, rm=a.regbits, reg=b.regbits)
+
+ def encode(self):
+ opcode = 0x31 # XOR r/m64, r64
+ # Alternative is 0x33 XOR r64, r/m64
+ code = bytes([opcode])
+ return self.rex.encode() + code + self.mod_rm.encode()
+
+
+# integer arithmatic:
+def addreg64(rega, regb):
+ if regb in regs64:
+ pre, post = prepost(regb, rega)
+ opcode = 0x01 # ADD r/m64, r64
+ return pre + [opcode] + post
+ elif type(regb) is int:
+ if regb < 100:
+ rexprefix = rex(w=1, b=rexbit[rega])
+ opcode = 0x83 # add r/m, imm8
+ mod_rm = modrm(3, rm=regs64[rega], reg=0)
+ return [rexprefix, opcode, mod_rm]+imm8(regb)
+ elif regb < (1<<31):
+ rexprefix = rex(w=1, b=rexbit[rega])
+ opcode = 0x81 # add r/m64, imm32
+ mod_rm = modrm(3, rm=regs64[rega], reg=0)
+ return [rexprefix, opcode, mod_rm]+imm32(regb)
+ else:
+ Error('Constant value too large!')
+ else:
+ Error('unknown second operand!'.format(regb))
+
+def subreg64(rega, regb):
+ if regb in regs64:
+ pre, post = prepost(regb, rega)
+ opcode = 0x29 # SUB r/m64, r64
+ return pre + [opcode] + post
+ elif type(regb) is int:
+ if regb < 100:
+ rexprefix = rex(w=1, b=rexbit[rega])
+ opcode = 0x83 # sub r/m, imm8
+ mod_rm = modrm(3, rm=regs64[rega], reg=5)
+ return [rexprefix, opcode, mod_rm]+imm8(regb)
+ elif regb < (1<<31):
+ rexprefix = rex(w=1, b=rexbit[rega])
+ opcode = 0x81 # sub r/m64, imm32
+ mod_rm = modrm(3, rm=regs64[rega], reg=5)
+ return [rexprefix, opcode, mod_rm]+imm32(regb)
+ else:
+ Error('Constant value too large!')
+
+ else:
+ Error('unknown second operand!'.format(regb))
+
+def idivreg64(reg):
+ rexprefix = rex(w=1, b=rexbit[reg])
+ opcode = 0xf7 # IDIV r/m64
+ mod_rm = modrm(3, rm=regs64[reg], reg=7)
+ return [rexprefix, opcode, mod_rm]
+
+def imulreg64_rax(reg):
+ rexprefix = rex(w=1, b=rexbit[reg])
+ opcode = 0xf7 # IMUL r/m64
+ mod_rm = modrm(3, rm=regs64[reg], reg=5)
+ return [rexprefix, opcode, mod_rm]
+
+def imulreg64(rega, regb):
+ pre, post = prepost(rega, regb)
+ opcode = 0x0f # IMUL r64, r/m64
+ opcode2 = 0xaf
+ return pre + [opcode, opcode2] + post
+
+
+def cmpreg64(rega, regb):
+ if regb in regs64:
+ pre, post = prepost(regb, rega)
+ opcode = 0x39 # CMP r/m64, r64
+ return pre + [opcode] + post
+ elif type(regb) is int:
+ rexprefix = rex(w=1, b=rexbit[rega])
+ opcode = 0x83 # CMP r/m64, imm8
+ mod_rm = modrm(3, rm=regs64[rega], reg=7)
+ return [rexprefix, opcode, mod_rm] + imm8(regb)
+ else:
+ Error('not implemented cmp64')
diff -r 5d03c10fe19d -r c0d9837acde8 python/ppci/target/x86/registers.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/python/ppci/target/x86/registers.py Thu May 29 12:13:37 2014 +0200
@@ -0,0 +1,52 @@
+"""
+ Contains register definitions for x86 target.
+"""
+from ..basetarget import Register
+
+
+class X86Register(Register):
+ def __init__(self, num, name):
+ super().__init__(name)
+ self.num = num
+
+ def __repr__(self):
+ return 'x86reg {}'.format(self.name)
+
+ @property
+ def rexbit(self):
+ return (self.num >> 3) & 0x1
+
+ @property
+ def regbits(self):
+ return self.num & 0x7
+
+# Calculation of the rexb bit:
+# rexbit = {'rax': 0, 'rcx':0, 'rdx':0, 'rbx': 0, 'rsp': 0, 'rbp': 0, 'rsi':0,
+# 'rdi':0,'r8':1,'r9':1,'r10':1,'r11':1,'r12':1,'r13':1,'r14':1,'r15':1}
+
+# regs64 = {'rax': 0,'rcx':1,'rdx':2,'rbx':3,'rsp':4,'rbp':5,'rsi':6,'rdi':7,
+# 'r8':0,'r9':1,'r10':2,'r11':3,'r12':4,'r13':5,'r14':6,'r15':7}
+# regs32 = {'eax': 0, 'ecx':1, 'edx':2, 'ebx': 3, 'esp': 4, 'ebp': 5, 'esi':6,
+# 'edi':7}
+# regs8 = {'al':0,'cl':1,'dl':2,'bl':3,'ah':4,'ch':5,'dh':6,'bh':7}
+rax = X86Register(0, 'rax')
+rcx = X86Register(1, 'rcx')
+rdx = X86Register(2, 'rdx')
+rbx = X86Register(3, 'rbx')
+rsp = X86Register(4, 'rsp')
+rbp = X86Register(5, 'rbp')
+rsi = X86Register(6, 'rsi')
+rdi = X86Register(7, 'rdi')
+
+r8 = X86Register(8, 'r8')
+r9 = X86Register(9, 'r9')
+r10 = X86Register(10, 'r10')
+r11 = X86Register(11, 'r11')
+r12 = X86Register(12, 'r12')
+r13 = X86Register(13, 'r13')
+r14 = X86Register(14, 'r14')
+r15 = X86Register(15, 'r15')
+
+low_regs = {rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi}
+
+regs64 = {r8, r9, r10, r11, r12, r13, r14, r15} | low_regs
diff -r 5d03c10fe19d -r c0d9837acde8 python/ppci/target/x86/target_x86.py
--- a/python/ppci/target/x86/target_x86.py Thu May 29 10:47:28 2014 +0200
+++ b/python/ppci/target/x86/target_x86.py Thu May 29 12:13:37 2014 +0200
@@ -1,66 +1,59 @@
-from target import Register, Instruction, Target
-
-class x86Register(Register):
- def __init__(self, name):
- self.name = name
-
-class REG16(x86Register):
- pass
-
-def addRegs(cls, names):
- for name in names:
- r = cls(name)
- globals()[name] = r
-
-addRegs(REG16, ['ax', 'bx', 'cx'])
+from ..basetarget import Target
+from ...assembler import BaseAssembler
+from .registers import rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi
+from .registers import r8, r9, r10, r11, r12, r13, r14, r15, regs64
+from .instructions import Mov, Inc, Xor, Push, Pop
-regs = """
-ax; reg16
-"""
-class MO:
- def __init__(self):
- pass
-
-instrs = """
-add; 0x0; mem8/reg8; reg8
-"""
-
-# machine op table:
-mot = []
-
-for i in instrs.split('\n'):
- i = i.strip()
- if i:
- print('INS:', i)
- mnemonic, opcode, op1, op2 = [a.strip() for a in i.split(';')]
- print(op1.split('/'), op2.split('/'))
+class X86Assembler(BaseAssembler):
+ def __init__(self, target):
+ super().__init__(target)
+ self.make_parser()
-print(mot)
+class X86Target(Target):
+ """ x86 target containing assembler, linker"""
+ def __init__(self):
+ super().__init__('x86')
-# Test first with these 3 instructions:
-"""
-mov reg64, reg64 : opcode=0x89
-xor reg64, reg64 : opcode=0x31
-inc reg64 : opcode=0xff
-"""
+ for reg in regs64:
+ self.add_keyword(reg.name)
-class x86Machine:
- def __init__(self):
- self.table = []
- self.table.append((0x0, 'add', 'reg8/mem8, reg8'))
- self.table.append((0x1, 'add', 'reg16/mem16/reg32/mem32, reg16/reg32'))
- self.table.append((0x2, 'add', 'reg8, reg8/mem8'))
- def forMnemonic(self, m):
- return [i for i in self.table if i[1] == m]
- def emit(self, m, ops):
- print(m, ops)
- ops = self.forMnemonic(m)
- print(ops)
+ self.add_rule('reg', ['rax'], lambda rhs: rax)
+ self.add_rule('reg', ['rcx'], lambda rhs: rcx)
+ self.add_rule('reg', ['rdx'], lambda rhs: rdx)
+ self.add_rule('reg', ['rbx'], lambda rhs: rbx)
+ self.add_rule('reg', ['rsp'], lambda rhs: rsp)
+ self.add_rule('reg', ['rbp'], lambda rhs: rbp)
+ self.add_rule('reg', ['rsi'], lambda rhs: rsi)
+ self.add_rule('reg', ['rdi'], lambda rhs: rdi)
+ self.add_rule('reg', ['r8'], lambda rhs: r8)
+ self.add_rule('reg', ['r9'], lambda rhs: r9)
+ self.add_rule('reg', ['r10'], lambda rhs: r10)
+ self.add_rule('reg', ['r11'], lambda rhs: r11)
+ self.add_rule('reg', ['r12'], lambda rhs: r12)
+ self.add_rule('reg', ['r13'], lambda rhs: r13)
+ self.add_rule('reg', ['r14'], lambda rhs: r14)
+ self.add_rule('reg', ['r15'], lambda rhs: r15)
+ self.add_keyword('mov')
+ self.add_instruction(['mov', 'reg', ',', 'reg'],
+ lambda rhs: Mov(rhs[1], rhs[3]))
-if __name__ == '__main__':
- m = x86Machine()
- m.emit('add', [ax, cx])
- m.emit('mov', [bx, 1337])
+ self.add_keyword('xor')
+ self.add_instruction(['xor', 'reg', ',', 'reg'],
+ lambda rhs: Xor(rhs[1], rhs[3]))
+
+ self.add_keyword('inc')
+ self.add_instruction(['inc', 'reg'],
+ lambda rhs: Inc(rhs[1]))
+
+ self.add_keyword('push')
+ self.add_instruction(['push', 'reg'],
+ lambda rhs: Push(rhs[1]))
+
+ self.add_keyword('pop')
+ self.add_instruction(['pop', 'reg'],
+ lambda rhs: Pop(rhs[1]))
+
+ self.assembler = X86Assembler(self)
diff -r 5d03c10fe19d -r c0d9837acde8 python/ppci/target/x86/x86.py
--- a/python/ppci/target/x86/x86.py Thu May 29 10:47:28 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-import ppci
-import ir
-
-class X86CodeGenSimple:
- """
- Inefficient code generation, assume stack machine
- backend
- """
- def __init__(self, diag):
- self.diag = diag
-
- def emit(self, i):
- self.asm.append(i)
-
- def genBin(self, ir):
- self.asm = []
- self.genModule(ir)
- return self.asm
-
- def genModule(self, ir):
- for f in ir.Functions:
- self.genFunction(f)
- def genFunction(self, f):
- self.emit('global {0}'.format(f.name))
- self.emit('{0}:'.format(f.name))
- self.emit('jmp {0}'.format(f.entry.name))
- for bb in f.BasicBlocks:
- self.genBB(bb)
- def genBB(self, bb):
- self.emit('{0}:'.format(bb.name))
- for i in bb.Instructions:
- self.genIns(i)
- def genIns(self, i):
- if type(i) is ir.BinaryOperator:
- ops = {'+':'add', '-':'sub', '*':'mul'}
- if i.operation in ops:
- i.result.reg = 'rax'
- i.value1.reg = 'rbx'
- i.value2.reg = 'rbx'
- self.emit('mov {0}, {1}'.format(i.result.reg, i.value1.reg))
- self.emit('{0} {1}, {2}'.format(ops[i.operation], i.result.reg, i.value2.reg))
- else:
- raise NotImplementedError('op {0}'.format(i.operation))
- elif type(i) is ir.Load:
- self.emit('mov {0}, [{1}]'.format(i.value, i.location))
- elif type(i) is ir.Return:
- self.emit('ret')
- elif type(i) is ir.Call:
- self.emit('call')
- elif type(i) is ir.ImmLoad:
- self.emit('mov {0}, {1}'.format(i.target, i.value))
- elif type(i) is ir.Store:
- self.emit('mov [{0}], {1}'.format(i.location, i.value))
- elif type(i) is ir.ConditionalBranch:
- self.emit('cmp {0}, {1}'.format(i.a, i.b))
- jmps = {'>':'jg', '<':'jl', '==':'je'}
- if i.cond in jmps:
- j = jmps[i.cond]
- self.emit('{0} {1}'.format(j, i.lab1.name))
- else:
- raise NotImplementedError('condition {0}'.format(i.cond))
- self.emit('jmp {0}'.format(i.lab2.name))
- elif type(i) is ir.Branch:
- self.emit('jmp {0}'.format(i.target.name))
- elif type(i) is ir.Alloc:
- pass
- else:
- raise NotImplementedError('{0}'.format(i))
-
diff -r 5d03c10fe19d -r c0d9837acde8 python/ppci/target/x86/x86_2.py
--- a/python/ppci/target/x86/x86_2.py Thu May 29 10:47:28 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-"""
- X86 target descriptions and encodings.
-
-"""
-
-from target import Register, Instruction, Target, Imm8, Label, Imm3, LabelRef
-
-
-modrm = {'rax': 0, 'rbx': 1}
-
-# Table 3.1 of the intel manual:
-# use REX.W on the table below:
-regs64 = {'rax': 0,'rcx':1,'rdx':2,'rbx':3,'rsp':4,'rbp':5,'rsi':6,'rdi':7,'r8':0,'r9':1,'r10':2,'r11':3,'r12':4,'r13':5,'r14':6,'r15':7}
-regs32 = {'eax': 0, 'ecx':1, 'edx':2, 'ebx': 3, 'esp': 4, 'ebp': 5, 'esi':6, 'edi':7}
-regs8 = {'al':0,'cl':1,'dl':2,'bl':3,'ah':4,'ch':5,'dh':6,'bh':7}
-
-# Calculation of the rexb bit:
-rexbit = {'rax': 0, 'rcx':0, 'rdx':0, 'rbx': 0, 'rsp': 0, 'rbp': 0, 'rsi':0, 'rdi':0,'r8':1,'r9':1,'r10':1,'r11':1,'r12':1,'r13':1,'r14':1,'r15':1}
-
-# Helper functions:
-def imm64(x):
- """ represent 64 bits integer in little endian 8 bytes"""
- if x < 0:
- x = x + (1 << 64)
- x = x & 0xFFFFFFFFFFFFFFFF
- return [ (x >> (p*8)) & 0xFF for p in range(8) ]
-
-def imm32(x):
- """ represent 32 bits integer in little endian 4 bytes"""
- if x < 0:
- x = x + (1 << 32)
- x = x & 0xFFFFFFFF
- return [ (x >> (p*8)) & 0xFF for p in range(4) ]
-
-def imm8(x):
- if x < 0:
- x = x + (1 << 8)
- x = x & 0xFF
- return [ x ]
-
-def modrm(mod=0, rm=0, reg=0):
- """ Construct the modrm byte from its components """
- assert(mod <= 3)
- assert(rm <= 7)
- assert(reg <= 7)
- return (mod << 6) | (reg << 3) | rm
-
-def rex(w=0, r=0, x=0, b=0):
- """ Create a REX prefix byte """
- assert(w <= 1)
- assert(r <= 1)
- assert(x <= 1)
- assert(b <= 1)
- return 0x40 | (w<<3) | (r<<2) | (x<<1) | b
-
-def sib(ss=0, index=0, base=0):
- assert(ss <= 3)
- assert(index <= 7)
- assert(base <= 7)
- return (ss << 6) | (index << 3) | base
-
-tttn = {'L':0xc,'G':0xf,'NE':0x5,'GE':0xd,'LE':0xe, 'E':0x4}
-
-# Actual instructions:
-def nearjump(distance, condition=None):
- """ jmp imm32 """
- lim = (1<<30)
- if abs(distance) > lim:
- Error('near jump cannot jump over more than {0} bytes'.format(lim))
- if condition:
- if distance < 0:
- distance -= 6 # Skip own instruction
- opcode = 0x80 | tttn[condition] # Jcc imm32
- return [0x0F, opcode] + imm32(distance)
- else:
- if distance < 0:
- distance -= 5 # Skip own instruction
- return [ 0xE9 ] + imm32(distance)
-
-def shortjump(distance, condition=None):
- """ jmp imm8 """
- lim = 118
- if abs(distance) > lim:
- Error('short jump cannot jump over more than {0} bytes'.format(lim))
- if distance < 0:
- distance -= 2 # Skip own instruction
- if condition:
- opcode = 0x70 | tttn[condition] # Jcc rel8
- else:
- opcode = 0xeb # jmp rel8
- return [opcode] + imm8(distance)
-
-# Helper that determines jump type:
-def reljump(distance):
- if abs(distance) < 110:
- return shortjump(distance)
- else:
- return nearjump(distance)
-
-def push(reg):
- if reg in regs64:
- if rexbit[reg] == 1:
- return [0x41, 0x50 + regs64[reg]]
- else:
- return [0x50 + regs64[reg]]
- else:
- Error('push for {0} not implemented'.format(reg))
-
-def pop(reg):
- if reg in regs64:
- if rexbit[reg] == 1:
- rexprefix = rex(b=1)
- opcode = 0x58 + regs64[reg]
- return [rexprefix, opcode]
- else:
- opcode = 0x58 + regs64[reg]
- return [ opcode ]
- else:
- Error('pop for {0} not implemented'.format(reg))
-
-def INT(number):
- opcode = 0xcd
- return [opcode] + imm8(number)
-
-def syscall():
- return [0x0F, 0x05]
-
-def call(distance):
- if type(distance) is int:
- return [0xe8]+imm32(distance)
- elif type(distance) is str and distance in regs64:
- reg = distance
- opcode = 0xFF # 0xFF /2 == call r/m64
- mod_rm = modrm(mod=3, reg=2, rm=regs64[reg])
- if rexbit[reg] == 1:
- rexprefix = rex(b=rexbit[reg])
- return [rexprefix, opcode, mod_rm]
- else:
- return [opcode, mod_rm]
- else:
- Error('Cannot call to {0}'.format(distance))
-
-def ret():
- return [ 0xc3 ]
-
-def increg64(reg):
- assert(reg in regs64)
- rexprefix = rex(w=1, b=rexbit[reg])
- opcode = 0xff
- mod_rm = modrm(mod=3, rm=regs64[reg])
- return [rexprefix, opcode, mod_rm]
-
-def prepost8(r8, rm8):
- assert(r8 in regs8)
- pre = []
- if type(rm8) is list:
- # TODO: merge mem access with prepost for 64 bits
- if len(rm8) == 1:
- base, = rm8
- if type(base) is str and base in regs64:
- assert(not base in ['rbp', 'rsp', 'r12', 'r13'])
- mod_rm = modrm(mod=0, rm=regs64[base], reg=regs8[r8])
- if rexbit[base] == 1:
- pre.append(rex(b=1))
- post = [mod_rm]
- else:
- Error('One arg of type {0} not implemented'.format(base))
- elif len(rm8) == 2:
- base, offset = rm8
- assert(type(offset) is int)
- assert(base in regs64)
-
- if base == 'rsp' or base == 'r12':
- Error('Cannot use rsp or r12 as base yet')
- if rexbit[base] == 1:
- pre.append( rex(b=1) )
- mod_rm = modrm(mod=1, rm=regs64[base], reg=regs8[r8])
- post = [mod_rm] + imm8(offset)
- else:
- Error('not supporting prepost8 with list len {0}'.format(len(rm8)))
- else:
- Error('Not supporting move with reg8 {0}'.format(r8))
- return pre, post
-
-def prepost(r64, rm64):
- assert(r64 in regs64)
- if type(rm64) is list:
- if len(rm64) == 3:
- base, index, disp = rm64
- assert(base in regs64)
- assert(index in regs64)
- assert(type(disp) is int)
- # Assert that no special cases are used:
- # TODO: swap base and index to avoid special cases
- # TODO: exploit special cases and make better code
- assert(index != 'rsp')
-
- rexprefix = rex(w=1, r=rexbit[r64], x=rexbit[index], b=rexbit[base])
- # mod=1 and rm=4 indicates a SIB byte: [--][--]+imm8
- mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
- si_b = sib(ss=0, index=regs64[index], base=regs64[base])
- return [rexprefix], [mod_rm, si_b] + imm8(disp)
- elif len(rm64) == 2:
- base, offset = rm64
- assert(type(offset) is int)
- if base == 'RIP':
- # RIP pointer relative addressing mode!
- rexprefix = rex(w=1, r=rexbit[r64])
- mod_rm = modrm(mod=0, rm=5, reg=regs64[r64])
- return [rexprefix], [mod_rm] + imm32(offset)
- else:
- assert(base in regs64)
-
- if base == 'rsp' or base == 'r12':
- # extended function that uses SIB byte
- rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
- # rm=4 indicates a SIB byte follows
- mod_rm = modrm(mod=1, rm=4, reg=regs64[r64])
- # index=4 indicates that index is not used
- si_b = sib(ss=0, index=4, base=regs64[base])
- return [rexprefix], [mod_rm, si_b] + imm8(offset)
- else:
- rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[base])
- mod_rm = modrm(mod=1, rm=regs64[base], reg=regs64[r64])
- return [rexprefix], [mod_rm] + imm8(offset)
- elif len(rm64) == 1:
- offset = rm64[0]
- if type(offset) is int:
- rexprefix = rex(w=1, r=rexbit[r64])
- mod_rm = modrm(mod=0, rm=4,reg=regs64[r64])
- si_b = sib(ss=0, index=4,base=5) # 0x25
- return [rexprefix], [mod_rm, si_b] + imm32(offset)
- else:
- Error('Memory reference of type {0} not implemented'.format(offset))
- else:
- Error('Memory reference not implemented')
- elif rm64 in regs64:
- rexprefix = rex(w=1, r=rexbit[r64], b=rexbit[rm64])
- mod_rm = modrm(3, rm=regs64[rm64], reg=regs64[r64])
- return [rexprefix], [mod_rm]
-
-def leareg64(rega, m):
- opcode = 0x8d # lea r64, m
- pre, post = prepost(rega, m)
- return pre + [opcode] + post
-
-def mov(rega, regb):
- if type(regb) is int:
- pre = [rex(w=1, b=rexbit[rega])]
- opcode = 0xb8 + regs64[rega]
- post = imm64(regb)
- elif type(regb) is str:
- if regb in regs64:
- opcode = 0x89 # mov r/m64, r64
- pre, post = prepost(regb, rega)
- elif regb in regs8:
- opcode = 0x88 # mov r/m8, r8
- pre, post = prepost8(regb, rega)
- else:
- Error('Unknown register {0}'.format(regb))
- elif type(rega) is str:
- if rega in regs64:
- opcode = 0x8b # mov r64, r/m64
- pre, post = prepost(rega, regb)
- else:
- Error('Unknown register {0}'.format(rega))
- else:
- Error('Move of this kind {0}, {1} not implemented'.format(rega, regb))
- return pre + [opcode] + post
-
-def xorreg64(rega, regb):
- rexprefix = rex(w=1, r=rexbit[regb], b=rexbit[rega])
- opcode = 0x31 # XOR r/m64, r64
- # Alternative is 0x33 XOR r64, r/m64
- mod_rm = modrm(3, rm=regs64[rega], reg=regs64[regb])
- return [rexprefix, opcode, mod_rm]
-
-# integer arithmatic:
-def addreg64(rega, regb):
- if regb in regs64:
- pre, post = prepost(regb, rega)
- opcode = 0x01 # ADD r/m64, r64
- return pre + [opcode] + post
- elif type(regb) is int:
- if regb < 100:
- rexprefix = rex(w=1, b=rexbit[rega])
- opcode = 0x83 # add r/m, imm8
- mod_rm = modrm(3, rm=regs64[rega], reg=0)
- return [rexprefix, opcode, mod_rm]+imm8(regb)
- elif regb < (1<<31):
- rexprefix = rex(w=1, b=rexbit[rega])
- opcode = 0x81 # add r/m64, imm32
- mod_rm = modrm(3, rm=regs64[rega], reg=0)
- return [rexprefix, opcode, mod_rm]+imm32(regb)
- else:
- Error('Constant value too large!')
- else:
- Error('unknown second operand!'.format(regb))
-
-def subreg64(rega, regb):
- if regb in regs64:
- pre, post = prepost(regb, rega)
- opcode = 0x29 # SUB r/m64, r64
- return pre + [opcode] + post
- elif type(regb) is int:
- if regb < 100:
- rexprefix = rex(w=1, b=rexbit[rega])
- opcode = 0x83 # sub r/m, imm8
- mod_rm = modrm(3, rm=regs64[rega], reg=5)
- return [rexprefix, opcode, mod_rm]+imm8(regb)
- elif regb < (1<<31):
- rexprefix = rex(w=1, b=rexbit[rega])
- opcode = 0x81 # sub r/m64, imm32
- mod_rm = modrm(3, rm=regs64[rega], reg=5)
- return [rexprefix, opcode, mod_rm]+imm32(regb)
- else:
- Error('Constant value too large!')
-
- else:
- Error('unknown second operand!'.format(regb))
-
-def idivreg64(reg):
- rexprefix = rex(w=1, b=rexbit[reg])
- opcode = 0xf7 # IDIV r/m64
- mod_rm = modrm(3, rm=regs64[reg], reg=7)
- return [rexprefix, opcode, mod_rm]
-
-def imulreg64_rax(reg):
- rexprefix = rex(w=1, b=rexbit[reg])
- opcode = 0xf7 # IMUL r/m64
- mod_rm = modrm(3, rm=regs64[reg], reg=5)
- return [rexprefix, opcode, mod_rm]
-
-def imulreg64(rega, regb):
- pre, post = prepost(rega, regb)
- opcode = 0x0f # IMUL r64, r/m64
- opcode2 = 0xaf
- return pre + [opcode, opcode2] + post
-
-def cmpreg64(rega, regb):
- if regb in regs64:
- pre, post = prepost(regb, rega)
- opcode = 0x39 # CMP r/m64, r64
- return pre + [opcode] + post
- elif type(regb) is int:
- rexprefix = rex(w=1, b=rexbit[rega])
- opcode = 0x83 # CMP r/m64, imm8
- mod_rm = modrm(3, rm=regs64[rega], reg=7)
- return [rexprefix, opcode, mod_rm] + imm8(regb)
-
- else:
- Error('not implemented cmp64')
-
-# Mapping that maps string names to the right functions:
-opcodes = {'mov':(mov,2), 'lea':(leareg64,2), 'int':(INT,1), 'syscall':(syscall,0)}
-
diff -r 5d03c10fe19d -r c0d9837acde8 test/testdiagrameditor.py
--- a/test/testdiagrameditor.py Thu May 29 10:47:28 2014 +0200
+++ b/test/testdiagrameditor.py Thu May 29 12:13:37 2014 +0200
@@ -21,6 +21,8 @@
skip_it = True
+if 'LCFOSGUITESTS' not in os.environ:
+ skip_it = True
class DiagramEditorTestCase(unittest.TestCase):
def setUp(self):
diff -r 5d03c10fe19d -r c0d9837acde8 test/testir.py
--- a/test/testir.py Thu May 29 10:47:28 2014 +0200
+++ b/test/testir.py Thu May 29 12:13:37 2014 +0200
@@ -70,10 +70,10 @@
self.b.emit(ir.Jump(bb))
self.b.setBlock(bb)
v1 = ir.Const(5)
- self.b.emit(v1)
+ # self.b.emit(v1)
v2 = ir.Const(7)
v3 = ir.Add(v1, v2, "add", ir.i32)
- self.b.emit(v3)
+ # self.b.emit(v3)
self.b.emit(ir.Jump(f.epiloog))
self.cf.run(self.m)
diff -r 5d03c10fe19d -r c0d9837acde8 test/testsamples.py
--- a/test/testsamples.py Thu May 29 10:47:28 2014 +0200
+++ b/test/testsamples.py Thu May 29 12:13:37 2014 +0200
@@ -5,36 +5,60 @@
from testzcc import relpath
from ppci.buildfunctions import assemble, c3compile, link
-startercode = """
-section reset
-mov sp, 0x30000 ; setup stack pointer
-BL sample_start ; Branch to sample start
-local_loop:
-B local_loop
+mod_io_src = """
+module io;
+import arch;
+
+function void println(string txt)
+{
+ print(txt);
+ arch.putc(10); // Newline!
+}
+
+function void print(string txt)
+{
+ var int i;
+ i = 0;
+
+ while (i < txt->len)
+ {
+ arch.putc(cast(txt->txt[i]));
+ i = i + 1;
+ }
+}
+
+// Print integer in hexadecimal notation:
+function void print_int(int i)
+{
+ print("0x");
+
+ // int txt[20];
+ var int b;
+ var int c;
+
+ for (b=28; b >= 0; b = b - 4)
+ {
+ c = (i >> b) & 0xF;
+ if (c < 10)
+ {
+ arch.putc( 48 + c );
+ }
+ else
+ {
+ arch.putc( 65 - 10 + c );
+ }
+ }
+
+ arch.putc(10); // Newline!
+}
+
+function void print2(string label, int value)
+{
+ print(label);
+ print_int(value);
+}
"""
-modarchcode = """
-module arch;
-
-function void putc(int c)
-{
- var int *UART0DR;
- UART0DR = cast(0x10009000); // UART0 DR register
- *UART0DR = c;
-}
-
-"""
-
-arch_mmap = """
-MEMORY image LOCATION=0x10000 SIZE=0x10000 {
- SECTION(reset)
- SECTION(code)
-}
-
-MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
- SECTION(data)
-}
-"""
class Samples:
def testPrint(self):
@@ -132,7 +156,7 @@
do5();
}
"""
- res = "".join("G=0x{0:08X}\n".format(a) for a in [1,2,7,8,13])
+ res = "".join("G=0x{0:08X}\n".format(a) for a in [1, 2, 7, 8, 13])
self.do(snippet, res)
@@ -142,6 +166,36 @@
self.skipTest('Not running qemu tests')
def do(self, src, expected_output):
+ startercode = """
+ section reset
+ mov sp, 0x30000 ; setup stack pointer
+ BL sample_start ; Branch to sample start
+ local_loop:
+ B local_loop
+ """
+
+ modarchcode = """
+ module arch;
+
+ function void putc(int c)
+ {
+ var int *UART0DR;
+ UART0DR = cast(0x10009000); // UART0 DR register
+ *UART0DR = c;
+ }
+
+ """
+
+ arch_mmap = """
+ MEMORY image LOCATION=0x10000 SIZE=0x10000 {
+ SECTION(reset)
+ SECTION(code)
+ }
+
+ MEMORY ram LOCATION=0x20000 SIZE=0x10000 {
+ SECTION(data)
+ }
+ """
# Construct binary file from snippet:
o1 = assemble(io.StringIO(startercode), 'arm')
o2 = c3compile([
@@ -164,6 +218,34 @@
self.assertEqual(expected_output, res)
+class TestSamplesOnX86(unittest.TestCase, Samples):
+ def setUp(self):
+ if not has_qemu():
+ self.skipTest('Not running qemu tests')
+ self.skipTest('No x86 target yet')
+
+ def do(self, src, expected_output):
+ # Construct binary file from snippet:
+ o1 = assemble(io.StringIO(startercode), 'x86')
+ o2 = c3compile([
+ relpath('..', 'kernel', 'src', 'io.c3'),
+ io.StringIO(modarchcode),
+ io.StringIO(src)], [], 'x86')
+ o3 = link([o2, o1], io.StringIO(arch_mmap), 'x86')
+
+ img_data = o3.get_image('image')
+ sample_filename = 'testsample.bin'
+ with open(sample_filename, 'wb') as f:
+ f.write(img_data)
+
+ # Check bin file exists:
+ self.assertTrue(os.path.isfile(sample_filename))
+
+ # Run bin file in emulator:
+ res = runQemu(sample_filename, machine='vexpress-a9')
+ os.remove(sample_filename)
+ self.assertEqual(expected_output, res)
+
# TODO: test samples on thumb target..
diff -r 5d03c10fe19d -r c0d9837acde8 test/testx86asm.py
--- a/test/testx86asm.py Thu May 29 10:47:28 2014 +0200
+++ b/test/testx86asm.py Thu May 29 12:13:37 2014 +0200
@@ -1,40 +1,46 @@
#!/usr/bin/python
import unittest
+from ppci.target.target_list import x86target
from testasm import AsmTestCaseBase
+from ppci.outstream import BinaryOutputStream
+from ppci.objectfile import ObjectFile
class AssemblerTestCase(AsmTestCaseBase):
- """
- test methods start with 'test*'
+ """
+ test methods start with 'test*'
Checks several assembly constructs agains their bytecodes
"""
def setUp(self):
- self.skipTest('not implemented yet')
- self.assembler = Assembler('x86-64')
- a = Assembler()
+ self.target = x86target
+ self.obj = ObjectFile()
+ self.ostream = BinaryOutputStream(self.obj)
+ self.ostream.select_section('code')
+ self.assembler = self.target.assembler
+ self.assembler.prepare()
- @unittest.skip
def testX86(self):
- self.feed('mov rax, rbx') # ; 0x48, 0x89, 0xd8
- self.feed('xor rcx, rbx') # ; 0x48, 0x31, 0xd9
- self.feed('inc rcx') # ; 0x48 0xff 0xc1
+ self.feed('mov rax, rbx')
+ self.feed('xor rcx, rbx')
+ self.feed('inc rcx')
self.check('48 89 d8 48 31 d9 48 ff c1')
-
- def tstAssembler(self):
- """ Check all kind of assembler cases """
- assert(assembler.shortjump(5) == [0xeb, 0x5])
- assert(assembler.shortjump(-2) == [0xeb, 0xfc])
- assert(assembler.shortjump(10,'GE') == [0x7d, 0xa])
- assert(assembler.nearjump(5) == [0xe9, 0x5,0x0,0x0,0x0])
- assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff])
- assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0])
+ @unittest.skip('not implemented')
+ def testJumpingAround(self):
+ """ Check all kind of assembler cases """
+ assert(assembler.shortjump(5) == [0xeb, 0x5])
+ assert(assembler.shortjump(-2) == [0xeb, 0xfc])
+ assert(assembler.shortjump(10,'GE') == [0x7d, 0xa])
+ assert(assembler.nearjump(5) == [0xe9, 0x5,0x0,0x0,0x0])
+ assert(assembler.nearjump(-2) == [0xe9, 0xf9, 0xff,0xff,0xff])
+ assert(assembler.nearjump(10,'LE') == [0x0f, 0x8e, 0xa,0x0,0x0,0x0])
+
+ @unittest.skip('not implemented')
def testCall(self):
self.feed('call r10')
self.check('')
self.feed('call rcx')
-
# assert(assembler.call('r10') == [0x41, 0xff, 0xd2])
# assert(assembler.call('rcx') == [0xff, 0xd1])
@@ -61,12 +67,14 @@
self.feed('pop r12')
self.check('5b 5d 41 5c')
+ @unittest.skip('not implemented')
def testAsmLoads(self):
- # TODO constant add testcases
- assert(assembler.mov('rbx', 'r14') == [0x4c, 0x89, 0xf3])
- assert(assembler.mov('r12', 'r8') == [0x4d, 0x89, 0xc4])
- assert(assembler.mov('rdi', 'rsp') == [0x48, 0x89, 0xe7])
+ self.feed('mov rbx, r14')
+ self.feed('mov r12, r8')
+ self.feed('mov rdi, rsp')
+ self.check('4c 89 f3 4d 89 c4 48 89 e7')
+ @unittest.skip('not implemented')
def testAsmMemLoads(self):
assert(assembler.mov('rax', ['r8','r15',0x11]) == [0x4b,0x8b,0x44,0x38,0x11])
assert(assembler.mov('r13', ['rbp','rcx',0x23]) == [0x4c,0x8b,0x6c,0xd,0x23])
@@ -79,6 +87,7 @@
assert(assembler.mov('r11', ['RIP', 0xf]) == [0x4c,0x8b,0x1d,0x0f,0x0,0x0,0x0])
+ @unittest.skip
def testAsmMemStores(self):
assert(assembler.mov(['rbp', 0x13],'rbx') == [0x48,0x89,0x5d,0x13])
assert(assembler.mov(['r12', 0x12],'r9') == [0x4d,0x89,0x4c,0x24,0x12])
@@ -90,6 +99,7 @@
assert(assembler.mov(['RIP', 0xf], 'r9') == [0x4c,0x89,0x0d,0x0f,0x0,0x0,0x0])
+ @unittest.skip
def testAsmMOV8(self):
assert(assembler.mov(['rbp', -8], 'al') == [0x88, 0x45, 0xf8])
assert(assembler.mov(['r11', 9], 'cl') == [0x41, 0x88, 0x4b, 0x09])
@@ -97,12 +107,14 @@
assert(assembler.mov(['rbx'], 'al') == [0x88, 0x03])
assert(assembler.mov(['r11'], 'dl') == [0x41, 0x88, 0x13])
+ @unittest.skip
def testAsmLea(self):
assert(assembler.leareg64('r11', ['RIP', 0xf]) == [0x4c,0x8d,0x1d,0x0f,0x0,0x0,0x0])
assert(assembler.leareg64('rsi', ['RIP', 0x7]) == [0x48,0x8d,0x35,0x07,0x0,0x0,0x0])
assert(assembler.leareg64('rcx', ['rbp', -8]) == [0x48,0x8d,0x4d,0xf8])
+ @unittest.skip
def testAssemblerCMP(self):
assert(assembler.cmpreg64('rdi', 'r13') == [0x4c, 0x39, 0xef])
assert(assembler.cmpreg64('rbx', 'r14') == [0x4c, 0x39, 0xf3])
@@ -111,6 +123,7 @@
assert(assembler.cmpreg64('rdi', 1) == [0x48, 0x83, 0xff, 0x01])
assert(assembler.cmpreg64('r11', 2) == [0x49, 0x83, 0xfb, 0x02])
+ @unittest.skip
def testAssemblerADD(self):
assert(assembler.addreg64('rbx', 'r13') == [0x4c, 0x01, 0xeb])
assert(assembler.addreg64('rax', 'rbx') == [0x48, 0x01, 0xd8])
@@ -120,6 +133,7 @@
assert(assembler.addreg64('r11', 0x1234567) == [0x49, 0x81, 0xc3, 0x67, 0x45,0x23,0x1])
assert(assembler.addreg64('rsp', 0x33) == [0x48, 0x83, 0xc4, 0x33])
+ @unittest.skip
def testAssemblerSUB(self):
assert(assembler.subreg64('rdx', 'r14') == [0x4c, 0x29, 0xf2])
assert(assembler.subreg64('r15', 'rbx') == [0x49, 0x29, 0xdf])
@@ -128,11 +142,13 @@
assert(assembler.subreg64('rsp', 0x123456) == [0x48, 0x81, 0xec, 0x56,0x34,0x12,0x0])
assert(assembler.subreg64('rsp', 0x12) == [0x48, 0x83, 0xec, 0x12])
+ @unittest.skip
def testAssemblerIDIV(self):
assert(assembler.idivreg64('r11') == [0x49, 0xf7, 0xfb])
assert(assembler.idivreg64('rcx') == [0x48, 0xf7, 0xf9])
assert(assembler.idivreg64('rsp') == [0x48, 0xf7, 0xfc])
+ @unittest.skip
def testAssemblerIMUL(self):
assert(assembler.imulreg64_rax('rdi') == [0x48, 0xf7, 0xef])
assert(assembler.imulreg64_rax('r10') == [0x49, 0xf7, 0xea])
@@ -147,4 +163,3 @@
if __name__ == '__main__':
unittest.main()
-
diff -r 5d03c10fe19d -r c0d9837acde8 user/build.xml
--- a/user/build.xml Thu May 29 10:47:28 2014 +0200
+++ b/user/build.xml Thu May 29 12:13:37 2014 +0200
@@ -22,11 +22,16 @@
includes="lib.c3;ipc.c3"
target="arm"
output="init.o"/>
+
+ objects="init.o;lib.o" />
+
+