[pypy-svn] r57954 - in pypy/branch/oo-jit/pypy/jit/codegen/x86_64: . test
witulski at codespeak.net
witulski at codespeak.net
Sun Sep 7 18:58:37 CEST 2008
Author: witulski
Date: Sun Sep 7 18:58:36 2008
New Revision: 57954
Modified:
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py
pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py
Log:
Added MUL and tests
FIXED IMM32 Problem ( supports now values grather than 255)
Add new Add test for big nums (test is broken)
Add CMP and SETG
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/assembler.py Sun Sep 7 18:58:36 2008
@@ -1,4 +1,5 @@
-from pypy.jit.codegen.x86_64.objmodel import Register64, Immediate32
+from pypy.jit.codegen.x86_64.objmodel import Register8, Register64, Immediate8, Immediate32
+
#Mapping from register to coding (Rex.W or Rex.B , ModRM)
REGISTER_MAP = {
@@ -19,14 +20,23 @@
"r14": (1, 6),
"r15": (1, 7),
}
-
+
+REGISTER_MAP_8BIT = {
+ "al":0,
+ "cl":1,
+ "dl":2,
+ }
+
# This method wirtes the bitencodings into
# the memory. The parameters are overwritten
# if one of the operands is an register
-def make_two_operand_instr(W = None, R = None, X = None, B = None, opcode =None, md1 = None, md2 = None):
+# tttn codes the flags and is only used by SETcc
+# extra is an extra byte for long opcodes like imul
+def make_two_operand_instr(W = None, R = None, X = None, B = None, opcode =None, m = None, md1 = None, md2 = None, tttn = None, extra = None):
def quadreg_instr(self, arg1, arg2):
# move the parameter
# to the inner function
+ mod = m
modrm1 = md1
modrm2 = md2
rexW = W
@@ -36,37 +46,44 @@
# Todo: other cases e.g memory as operand
if isinstance(arg1,Register64):
rexR, modrm1 = self.get_register_bits(arg1.reg)
-
- if isinstance(arg2,Register64):
- rexB, modrm2 = self.get_register_bits(arg2.reg)
+ elif isinstance(arg1,Register8):
+ modrm1 = self.get_register_bits_8Bit(arg1.reg)
# exchange the two arguments (modrm2/modrm1)
if isinstance(arg2,Immediate32):
+ # e.g: IMUL
+ if(modrm2=="sameReg"):
+ modrm2 = modrm1
+ rexB = rexR
self.write_rex_byte(rexW, rexR, rexX, rexB)
self.write(opcode)
self.write_modRM_byte(3, modrm2, modrm1)
- # FIXME: Bad solution
- # TODO: support values > 255
- if(arg2.value<256):
- self.write(chr(arg2.value))
- self.write(chr(0))
- self.write(chr(0))
- self.write(chr(0))
- else:
+ self.writeImm32(arg2.value)
+ elif isinstance(arg2,Immediate8):
+ self.write_rex_byte(rexW, rexR, rexX, rexB)
+ self.write(opcode)
+ self.write_modRM_byte(3, modrm2, modrm1)
+ self.write(chr(arg2.value))
+ elif isinstance(arg2,Register64):
+ rexB, modrm2 = self.get_register_bits(arg2.reg)
# FIXME: exchange the two arguments (rexB/rexR)
self.write_rex_byte(rexW, rexB, rexX, rexR)
self.write(opcode)
- self.write_modRM_byte(3, modrm2, modrm1)
+ # used in imul
+ if not extra == None:
+ self.write(extra)
+ self.write_modRM_byte(mod, modrm2, modrm1)
return quadreg_instr
# This method wirtes the bitencodings into
# the memory. The parameters are overwritten
# if one of the operands is an register
-def make_one_operand_instr(W = None, R = None, X = None, B = None, opcode = None, md1 = None, md2 = None):
+def make_one_operand_instr(W = None, R = None, X = None, B = None, opcode = None, m = None, md1 = None, md2 = None, tttn=None, extra = None):
def quadreg_instr(self, arg1):
# move the parameter
# to the inner function
+ mod = m
modrm1 = md1
modrm2 = md2
rexW = W
@@ -77,13 +94,18 @@
# Todo: other cases e.g memory as operand
if isinstance(arg1,Register64):
rexB, modrm1 = self.get_register_bits(arg1.reg)
+ if isinstance(arg1,Register8):
+ modrm1 = self.get_register_bits_8Bit(arg1.reg)
# rexW(1) = 64bitMode
self.write_rex_byte(rexW, rexR, rexX, rexB)
self.write(opcode)
- self.write_modRM_byte(3, modrm2, modrm1)
+ if not tttn == None:
+ byte = (9 << 4) | tttn
+ self.write(chr(byte))
+ self.write_modRM_byte(mod, modrm2, modrm1)
return quadreg_instr
-
+
class X86_64CodeBuilder(object):
""" creats x86_64 opcodes"""
def write(self, data):
@@ -96,29 +118,47 @@
# The opcodes differs depending on the operands
+ # Params:
+ # W, R, X, B, Opcode, mod, modrm1, modrm2
# FIXME: rexX,rexB are set
- _ADD_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, 0, "\x81", None, 2)
- _ADD_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x00", None, None)
+ _ADD_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, 0, "\x81", 3, None, 2)
+ _ADD_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x00", 3, None, None)
- _DEC_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", None, 1)
- _INC_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", None, 0)
+ # FIXME: rexB is set
+ _CMP_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, 1, "\x81", 3, None, 7)
+ _CMP_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x39", 3, None, None)
+ # FIXME: rex B is set
+ _CMP_8REG_IMM8 = make_two_operand_instr( 0, 0, 0, 0, "\x82", 3, None, 7)
+
+ _DEC_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", 3, None, 1)
+ _INC_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", 3, None, 0)
- _MOV_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, None, "\xC7", None, 0)
- _MOV_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x89", None, None)
+ _MOV_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, None, "\xC7", 3, None, 0)
+ _MOV_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x89", 3, None, None)
+
+ _IMUL_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x0F", 3, None, None, None, "\xAF")
+ _IMUL_QWREG_IMM32 = make_two_operand_instr( 1, None, 0, None, "\x69", 3, None, "sameReg")
# FIXME: rexW is set
- _POP_QWREG = make_one_operand_instr( 1, 0, 0, None, "\x8F", None, 0)
- _PUSH_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", None, 6)
+ _POP_QWREG = make_one_operand_instr( 1, 0, 0, None, "\x8F", 3, None, 0)
+ _PUSH_QWREG = make_one_operand_instr( 1, 0, 0, None, "\xFF", 3, None, 6)
- _SUB_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x28", None, None)
+ _SETG_8REG = make_one_operand_instr( 0, 0, 0, 0, "\x0F", 3, None, 0,15)
+
+ _SUB_QWREG_QWREG = make_two_operand_instr( 1, None, 0, None, "\x28", 3, None, None)
+ _SUB_QWREG_IMM32 = make_two_operand_instr( 1, 0, 0, 0, "\x81", 3, None, 5)
# TODO: maybe a problem with more ore less than two arg.
def ADD(self, op1, op2):
method = getattr(self, "_ADD"+op1.to_string()+op2.to_string())
method(op1, op2)
+ def CMP(self, op1, op2):
+ method = getattr(self, "_CMP"+op1.to_string()+op2.to_string())
+ method(op1, op2)
+
def DEC(self, op1):
method = getattr(self, "_DEC"+op1.to_string())
method(op1)
@@ -127,6 +167,10 @@
method = getattr(self, "_INC"+op1.to_string())
method(op1)
+ def JMP(self,displ):
+ self.write("\xE9")
+ self.writeImm32(displ)
+
def POP(self, op1):
method = getattr(self, "_POP"+op1.to_string())
method(op1)
@@ -138,10 +182,23 @@
def MOV(self, op1, op2):
method = getattr(self, "_MOV"+op1.to_string()+op2.to_string())
method(op1, op2)
+
+ def IMUL(self, op1, op2):
+ method = getattr(self, "_IMUL"+op1.to_string()+op2.to_string())
+ # exchange the two arguments because
+ # the result is in the first register
+ if(op1.to_string()=="_QWREG" and op2.to_string()=="_QWREG"):
+ method(op2, op1)
+ else:
+ method(op1, op2)
def RET(self):
self.write("\xC3")
+ def SETG(self, op1):
+ method = getattr(self, "_SETG"+op1.to_string())
+ method(op1)
+
def SUB(self, op1, op2):
method = getattr(self, "_SUB"+op1.to_string()+op2.to_string())
method(op1, op2)
@@ -149,6 +206,22 @@
def get_register_bits(self, register):
return REGISTER_MAP[register]
+ def get_register_bits_8Bit(self, register):
+ return REGISTER_MAP_8BIT[register]
+
+ # Parse the integervalue to an charakter
+ # and write it
+ def writeImm32(self, imm32):
+ x = hex(imm32)
+ # parse to string and cut "0x" off
+ # fill with zeros if to short
+ y = "0"*(10-len(x))+x[2:len(x)]
+ assert len(y) == 8
+ self.write(chr(int(y[6:8],16)))
+ self.write(chr(int(y[4:6],16)))
+ self.write(chr(int(y[2:4],16)))
+ self.write(chr(int(y[0:2],16)))
+
# Rex-Prefix 4WRXB see AMD vol3 page 45
def write_rex_byte(self, rexW, rexR, rexX, rexB):
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/objmodel.py Sun Sep 7 18:58:36 2008
@@ -1,7 +1,17 @@
from pypy.jit.codegen import model
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
# Wrapper Classes
# The opcaodes differ from the type of
# the operand. So every wrapper is necessary
+# The to string method is used to choose the right
+# method inside the assembler
+class Register8(model.GenVar):
+ def __init__(self, reg):
+ self.reg = reg
+
+ def to_string(self):
+ return "_8REG"
+
class Register64(model.GenVar):
def __init__(self, reg):
self.reg = reg
@@ -9,6 +19,13 @@
def to_string(self):
return "_QWREG"
+class Immediate8(model.GenConst):
+ def __init__(self, value):
+ self.value = value
+
+ def to_string(self):
+ return "_IMM8"
+
class Immediate32(model.GenConst):
def __init__(self, value):
self.value = value
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/rgenop.py Sun Sep 7 18:58:36 2008
@@ -1,16 +1,17 @@
from pypy.jit.codegen import model
from pypy.rlib.objectmodel import specialize
-from pypy.jit.codegen.x86_64.objmodel import Register64, Immediate32
+from pypy.jit.codegen.x86_64.objmodel import Register8, Register64, Immediate8, Immediate32
from pypy.jit.codegen.x86_64.codebuf import InMemoryCodeBuilder
#TODO: understand llTypesystem
from pypy.rpython.lltypesystem import llmemory, lltype
from pypy.jit.codegen.ia32.objmodel import LL_TO_GENVAR
+from pypy.jit.codegen.model import GenLabel
# TODO: support zero arg.
-# This method calles the assembler to generate code.
+# This method calls the assembler to generate code.
# It saves the operands in the helpregister gv_z
# and determine the Type of the operands,
# to choose the right method in assembler.py
@@ -39,11 +40,18 @@
arg = lltype.Void
return LL_TO_GENVAR[arg]
+class Label(GenLabel):
+ def __init__(self, startaddr, arg_positions, stackdepth):
+ self.startaddr = startaddr
+ self.arg_positions = arg_positions
+ self.stackdepth = stackdepth
+
class Builder(model.GenBuilder):
MC_SIZE = 65536
+ #FIXME: The MemCodeBuild. is not opend in an _open method
def __init__(self):
self.mc = InMemoryCodeBuilder(self.MC_SIZE)
#callee-saved registers are commented out
@@ -51,18 +59,21 @@
"rax":None,
"rcx":None,
"rdx":None,
- # "rbx":None,
+ # "rbx":None,
"rsi":None,
"rdi":None,
"r8": None,
"r9": None,
"r10":None,
- # "r11":None,
- # "r12":None,
- # "r13":None,
- # "r14":None,
- # "r15":None,
+ # "r11":None,
+ # "r12":None,
+ # "r13":None,
+ # "r14":None,
+ # "r15":None,
}
+
+ def _open(self):
+ pass
@specialize.arg(1)
def genop1(self, opname, gv_arg):
@@ -75,16 +86,42 @@
return genmethod(gv_arg1, gv_arg2)
op_int_add = make_two_argument_method("ADD")
- op_int_sub = make_two_argument_method("SUB")
- op_int_inc = make_one_argument_method("INC")
op_int_dec = make_one_argument_method("DEC")
+ op_int_inc = make_one_argument_method("INC")
+ op_int_mul = make_two_argument_method("IMUL")
op_int_push = make_one_argument_method("PUSH")
op_int_pop = make_one_argument_method("POP")
+ op_int_sub = make_two_argument_method("SUB")
+
+ def jump_if_true(self, gv_condition, args_for_jump_gv):
+ targetbuilder = Builder()
+ self.mc.CMP(gv_condition, Immediate8(0))
+ #targetbuilder.come_from(self.mc, 'JNE')
+ return targetbuilder
+
+ def op_int_gt(self, gv_x, gv_y):
+ self.mc.CMP(gv_x, gv_y)
+ # You can not use evry register for
+ # 8 bit operations, so you have to
+ # choose rax,rcx or rdx
+ # TODO: rcx rdx
+ gv_z = self.allocate_register("rax")
+ self.mc.SETG(Register8("al"))
+ return Register8("al")
def finish_and_return(self, sigtoken, gv_returnvar):
#self.mc.write("\xB8\x0F\x00\x00\x00")
+ self._open()
self.mc.MOV(Register64("rax"), gv_returnvar)
self.mc.RET()
+ self._close()
+
+ #TODO: Implementation
+ def finish_and_goto(self, outputargs_gv, target):
+ self._open()
+ #FIXME: startaddr is maybe not 32bit
+ self.mc.JMP(target.startaddr)
+ self._close()
def allocate_register(self, register=None):
if register is None:
@@ -97,6 +134,14 @@
def end(self):
pass
+
+ #TODO: Implementation
+ def enter_next_block(self, args_gv):
+ print "WriteMe: enter_next_block"
+ return Label(self.mc.tell(), [], 0)
+
+ def _close(self):
+ pass
class RX86_64GenOp(model.AbstractRGenOp):
@@ -110,7 +155,7 @@
# wrappes a integer value
def genconst(self, llvalue):
T = lltype.typeOf(llvalue)
- # TODO: other cases(?)
+ # TODO: other cases(?),imm64
if T is lltype.Signed:
return Immediate32(llvalue)
@@ -122,6 +167,7 @@
entrypoint = builder.mc.tell()
# TODO: support more than two reg
register_list = ["rdi","rsi"]
+ # fill the list with the correct registers
inputargs_gv = [builder.allocate_register(register_list[i])
for i in range(len(arg_tokens))]
return builder,Immediate32(entrypoint), inputargs_gv
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_rgenop.py Sun Sep 7 18:58:36 2008
@@ -10,6 +10,24 @@
def skip(self):
py.test.skip("not implemented yet")
+def make_mul(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ builder, gv_mul, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "mul")
+ builder.start_writing()
+ gv_result = builder.genop2("int_mul", gv_x, gv_y)
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+ return gv_mul
+
+def make_mul_im32(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
+ builder, gv_mul, [gv_x, gv_y] = rgenop.newgraph(sigtoken, "mul")
+ builder.start_writing()
+ gv_result = builder.genop2("int_mul", gv_x, rgenop.genconst(200))
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+ return gv_mul
+
def make_inc(rgenop):
sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed], lltype.Signed))
builder, gv_inc, gv_x = rgenop.newgraph(sigtoken, "inc")
@@ -28,29 +46,63 @@
builder.end()
return gv_dec
+def make_push(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed], lltype.Signed))
+ builder, gv_push, gv_x = rgenop.newgraph(sigtoken, "push")
+ builder.start_writing()
+ gv_result = builder.genop1("int_push", gv_x[0])
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+ return gv_push
+
+def make_pop(rgenop):
+ sigtoken = rgenop.sigToken(lltype.FuncType([lltype.Signed], lltype.Signed))
+ builder, gv_pop, gv_x = rgenop.newgraph(sigtoken, "pop")
+ builder.start_writing()
+ gv_result = builder.genop1("int_pop", gv_x[0])
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+ return gv_pop
+
class TestRGenopDirect(AbstractRGenOpTestsDirect):
RGenOp = RX86_64GenOp
def test_inc(self):
rgenop = self.RGenOp()
- inc_result = make_inc(rgenop)
- fnptr = self.cast(inc_result,1)
+ inc_function = make_inc(rgenop)
+ fnptr = self.cast(inc_function,1)
res = fnptr(0)
assert res == 1
def test_dec(self):
rgenop = self.RGenOp()
- dec_result = make_dec(rgenop)
- fnptr = self.cast(dec_result,1)
+ dec_function = make_dec(rgenop)
+ fnptr = self.cast(dec_function,1)
res = fnptr(2)
assert res == 1
- #def test_push_and_pop(self):
- # rgenop = self.RGenOp()
- # push_result = make_push(rgenop)
- # fnptr = self.cast(push_result,1)
- # res = fnptr(2)
- # assert res == 1
+ def test_mul_im32(self):
+ rgenop = self.RGenOp()
+ mul_function = make_mul_im32(rgenop)
+ fnptr = self.cast(mul_function,1)
+ res = fnptr(210)
+ assert res == 42000
+
+ def test_mul(self):
+ rgenop = self.RGenOp()
+ mul_function = make_mul(rgenop)
+ fnptr = self.cast(mul_function,2)
+ res = fnptr(1200,300)
+ assert res == 360000
+
+ # def test_push_and_pop(self):
+ # rgenop = self.RGenOp()
+ # push_result = make_push(rgenop)
+ # fnptr = self.cast(push_result,1)
+ # pop_result = make_pop(rgenop)
+ # fnptr = self.cast(pop_result,1)
+ # res = fnptr(42)
+ #assert res == 1
test_directtesthelper_direct = skip
test_dummy_compile = skip
@@ -61,7 +113,7 @@
test_dummy_direct = skip
test_largedummy_direct = skip
test_branching_direct = skip
- test_goto_direct = skip
+ ##test_goto_direct = skip##
test_if_direct = skip
test_switch_direct = skip
test_large_switch_direct = skip
Modified: pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py (original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/x86_64/test/test_simple.py Sun Sep 7 18:58:36 2008
@@ -8,18 +8,28 @@
rgenop = RX86_64GenOp()
-def make_testbuilder():
- FUNC = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) #the funtiontype(arguments,returntype) of the graph we will create
+def make_testbuilder(num_of_args):
+ FUNC = lltype.FuncType([lltype.Signed]*num_of_args, lltype.Signed) #the funtiontype(arguments,returntype) of the graph we will create
token = rgenop.sigToken(FUNC)
builder, entrypoint, inputargs_gv = rgenop.newgraph(token, "test")
builder.start_writing()
- ctypestypes = [c_long, c_long]
+ ctypestypes = [c_long]*num_of_args
fp = cast(c_void_p(entrypoint.value),
CFUNCTYPE(c_long, *ctypestypes))
return builder, fp, inputargs_gv, token
+def test_add_big_num():
+ builder, fp, inputargs_gv, token = make_testbuilder(2)
+ genv0 = inputargs_gv[0] #the first argument "place"
+ genv1 = inputargs_gv[1]
+ genv_result = builder.genop2("int_add", genv0, genv1) #creates the addition and returns the place(register) of the result in genv_result
+ builder.finish_and_return(token, genv_result)
+ num = fp(1280, 1000)
+ assert num == 2280
+ print num
+
def test_add():
- builder, fp, inputargs_gv, token = make_testbuilder()
+ builder, fp, inputargs_gv, token = make_testbuilder(2)
genv0 = inputargs_gv[0] #the first argument "place"
genv1 = inputargs_gv[1]
genv_result = builder.genop2("int_add", genv0, genv1) #creates the addition and returns the place(register) of the result in genv_result
@@ -28,20 +38,38 @@
assert ten == 10
print ten
+def test_add_imm32():
+ builder, fp, inputargs_gv, token = make_testbuilder(1)
+ genv0 = inputargs_gv[0] #the first argument "place"
+ genv_result = builder.genop2("int_add", genv0, rgenop.genconst(1000)) #creates the addition and returns the place(register) of the result in genv_result
+ builder.finish_and_return(token, genv_result)
+ num = fp(1111)
+ assert num == 2111
+ print num
+
def test_ret():
- builder, fp, inputargs_gv, token = make_testbuilder()
+ builder, fp, inputargs_gv, token = make_testbuilder(1)
builder.finish_and_return(token, inputargs_gv[0])
print repr("".join(builder.mc._all))
- four = fp(4, 17)
+ four = fp(4)
assert four == 4
print four
def test_sub():
- builder, fp, inputargs_gv, token = make_testbuilder()
+ builder, fp, inputargs_gv, token = make_testbuilder(2)
genv0 = inputargs_gv[0] #the first argument "place"
genv1 = inputargs_gv[1]
- genv_result = builder.genop2("int_sub", genv0, genv1) #creates the addition and returns the place(register) of the result in genv_result
+ genv_result = builder.genop2("int_sub", genv0, genv1) #creates the subtraction and returns the place(register) of the result in genv_result
builder.finish_and_return(token, genv_result)
four = fp(10, 6)
assert four == 4
- print four
\ No newline at end of file
+ print four
+
+def test_sub_imm32():
+ builder, fp, inputargs_gv, token = make_testbuilder(1)
+ genv0 = inputargs_gv[0] #the first argument "place"
+ genv_result = builder.genop2("int_sub", genv0, rgenop.genconst(2)) #creates the subtraction and returns the place(register) of the result in genv_result
+ builder.finish_and_return(token, genv_result)
+ eight = fp(10)
+ assert eight == 8
+ print eight
\ No newline at end of file
More information about the Pypy-commit
mailing list