Mercurial > lcfOS
changeset 398:c0d9837acde8
x86 target refactor
author | Windel Bouwman |
---|---|
date | Thu, 29 May 2014 12:13:37 +0200 |
parents | 5d03c10fe19d |
children | a7c444404df9 |
files | kernel/arch/qemu_vexpress/layout.mmap kernel/build.xml kernel/ramdisk.asm python/ppci/target/arm/__init__.py python/ppci/target/msp430/msp430.py python/ppci/target/target_list.py python/ppci/target/token.py python/ppci/target/x86/__init__.py python/ppci/target/x86/instructions.py python/ppci/target/x86/registers.py python/ppci/target/x86/target_x86.py python/ppci/target/x86/x86.py python/ppci/target/x86/x86_2.py test/testdiagrameditor.py test/testir.py test/testsamples.py test/testx86asm.py user/build.xml |
diffstat | 18 files changed, 727 insertions(+), 553 deletions(-) [+] |
line wrap: on
line diff
--- 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 {
--- 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 @@ <assemble source="arch/qemu_vexpress/start.asm" target="arm" output="start.o" /> + <assemble source="ramdisk.asm" + target="arm" output="ramdisk.o" /> + <compile target="arm" sources='arch/qemu_vexpress/vexpressA9.c3' includes="${src}/*.c3" output="vexp.o" /> @@ -23,7 +26,7 @@ <link output="kernel.o" target="arm" layout="arch/qemu_vexpress/layout.mmap" - objects="henkie.o;vexp.o;start.o" /> + objects="henkie.o;vexp.o;start.o;ramdisk.o" /> <objcopy objectfile="kernel.o"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/ramdisk.asm Thu May 29 12:13:37 2014 +0200 @@ -0,0 +1,5 @@ + +section ramdisk + +ramdisk_begin: +
--- a/python/ppci/target/arm/__init__.py Thu May 29 10:47:28 2014 +0200 +++ b/python/ppci/target/arm/__init__.py Thu May 29 12:13:37 2014 +0200 @@ -4,7 +4,8 @@ from ..arm.registers import R8, R9, R10, R11, R12, SP, LR, PC from ..arm.registers import register_range -from .instructions import Dcd, Mov, Mov1, Add, Add2, Sub, Orr1, Mul, Mov2, Add1, Mul1 +from .instructions import Dcd, Mov, Mov1, Add, Add2, Sub, Orr1, Mul, Mov2 +from .instructions import Add1, Mul1 from .instructions import Lsr1, Lsl1, And1, Sub1 from .instructions import B, Bl, Ble, Bgt, Beq, Blt, Cmp, Cmp2 from .instructions import Push, Pop, Str, Ldr, Ldr3, Str1, Ldr1, Adr @@ -26,6 +27,7 @@ self.target.add_instruction(['repeat', 'imm32'], self.begin_repeat) self.target.add_instruction(['endrepeat'], self.end_repeat) + # Construct the parser from the given rules: self.make_parser() self.lit_pool = [] self.lit_counter = 0 @@ -101,7 +103,6 @@ outs.emit(Label(lname)) outs.emit(Dcd(0)) - def make_parser(self): # Assembly grammar: self.add_keyword('r0')
--- a/python/ppci/target/msp430/msp430.py Thu May 29 10:47:28 2014 +0200 +++ b/python/ppci/target/msp430/msp430.py Thu May 29 12:13:37 2014 +0200 @@ -49,17 +49,16 @@ self.assembler = Msp430Assembler(self) + self.registers.append(r10) + self.registers.append(r11) + self.registers.append(r12) + self.registers.append(r13) + self.registers.append(r14) + self.registers.append(r15) -msp430target = Msp430Target() # Target description for the MSP430 processor -msp430target.registers.append(r10) -msp430target.registers.append(r11) -msp430target.registers.append(r12) -msp430target.registers.append(r13) -msp430target.registers.append(r14) -msp430target.registers.append(r15)
--- a/python/ppci/target/target_list.py Thu May 29 10:47:28 2014 +0200 +++ b/python/ppci/target/target_list.py Thu May 29 12:13:37 2014 +0200 @@ -1,12 +1,19 @@ + +""" + Contains a list of instantiated targets. +""" from .arm import ArmTarget from .thumb import ThumbTarget -from .msp430.msp430 import msp430target +from .msp430.msp430 import Msp430Target +from .x86.target_x86 import X86Target # Instance: arm_target = ArmTarget() thumb_target = ThumbTarget() +x86target = X86Target() +msp430target = Msp430Target() -target_list = [arm_target, thumb_target] +target_list = [arm_target, thumb_target, x86target, msp430target] targets = {t.name: t for t in target_list} targetnames = list(targets.keys())
--- a/python/ppci/target/token.py Thu May 29 10:47:28 2014 +0200 +++ b/python/ppci/target/token.py Thu May 29 12:13:37 2014 +0200 @@ -1,6 +1,7 @@ import struct + def u16(h): return struct.pack('<H', h) @@ -9,16 +10,21 @@ return struct.pack('<I', x) +def u8(x): + return struct.pack('<B', x) + + def val2bit(v, bits): b = [] for i in range(bits): - b.append(bool((1<<i) & v)) + b.append(bool((1 << i) & v)) return b def bit_range(b, e): """ Property generator function """ getter = lambda s: s[b:e] + def setter(s, v): s[b:e] = v return property(getter, setter) @@ -53,4 +59,3 @@ self.set_bit(i, value_bits[i - key.start]) else: raise KeyError() -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ppci/target/x86/__init__.py Thu May 29 12:13:37 2014 +0200 @@ -0,0 +1,2 @@ + +# Make this a package.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ppci/target/x86/instructions.py Thu May 29 12:13:37 2014 +0200 @@ -0,0 +1,426 @@ +""" + X86 target descriptions and encodings. +""" + +from ..basetarget import Register, Instruction +from .registers import regs64, X86Register + +from ..token import Token, u32, u8, bit_range + + +modrm = {'rax': 0, 'rbx': 1} + +# Table 3.1 of the intel manual: +# use REX.W on the table below: + + +# 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 ] + + +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')
--- /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
--- 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)
--- 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)) -
--- 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)} -
--- 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):
--- 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)
--- 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<int>(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<int*>(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<int*>(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..
--- 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() -
--- 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"/> + <link output="init" layout="app.mmap" target="arm" - objects="init.o;lib.o"/> + objects="init.o;lib.o" /> + + <objcopy objectfile="init" + imagename="flash" + output="init.bin" /> </target> </project>