Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2299.mcz ==================== Summary ==================== Name: VMMaker.oscog-eem.2299 Author: eem Time: 21 December 2017, 9:17:52.747344 pm UUID: 53b6a352-dbde-430a-9ec1-cb56154fe2c5 Ancestors: VMMaker.oscog-eem.2298 Get the StackInterpreterSimulator to a state where it can correctly simulate the DoubleByteArray, WordArray, DoubleWordArray and MemoryTests. Principally allow the SqueakFFIPrims plugin (ThreadedFFIPlugin) to load and make primitiveFFIIntegerAt[Put] function correctly in simulation. Change the two primitives to use unalignedShortAt:[put:], unalignedLong32At:[put:] & unalignedLong64At:[put:] and implement these in SpurMemoryManager (ObjectMemory can wait) and have the preambleCCode map these to the original shortAt[put], long32At[put] & long32At[put] C functions/macros. Fix a bug in the simulation of LargeIntegersPlugin>>cDigitSub:len:with:len:into: (Nicolas, there may be similar signedness issues in other functions. If you have time and energy please consider taking a look at the code in the simulator). Fix a slip in the range comparison for 64-bit integer arguments in genPrimitiveAtPut. =============== Diff against VMMaker.oscog-eem.2298 =============== Item was added: + ----- Method: CoInterpreter>>ISA (in category 'simulation') ----- + ISA + <doNotGenerate> + ^cogit backEnd class ISA! Item was changed: ----- Method: CogClass>>cCoerceSimple:to: (in category 'translation support') ----- cCoerceSimple: value to: cTypeString <doNotGenerate> "Type coercion for translation and simulation. For simulation answer a suitable surrogate for the struct types" ^cTypeString caseOf: { [#'unsigned long'] -> [value]. [#'unsigned int'] -> [value]. + [#'unsigned short'] -> [value]. + [#sqInt] -> [value]. - [#sqInt] -> [value]. [#'sqIntptr_t'] -> [value]. [#'usqIntptr_t'] -> [value]. [#usqInt] -> [value]. [#sqLong] -> [value]. + [#usqLong] -> [value]. - [#usqLong] -> [value]. [#'AbstractInstruction *'] -> [value]. [#'BytecodeFixup *'] -> [value]. [#'CogMethod *'] -> [value]. [#'char *'] -> [value]. [#'sqInt *'] -> [value]. [#'void *'] -> [value]. [#void] -> [value]. [#'void (*)()'] -> [value]. [#'void (*)(void)'] -> [value]. [#'unsigned long (*)(void)'] -> [value]. [#'void (*)(unsigned long,unsigned long)'] -> [value]. [#'usqIntptr_t (*)(void)'] -> [value] }! Item was changed: ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveAtPut (in category 'primitive generators') ----- (excessive size, no diff calculated) Item was changed: ----- Method: FFIPlugin class>>moduleName (in category 'translation') ----- moduleName "FFIPlugin translate" "IMPORTANT: IF YOU CHANGE THE NAME OF THIS PLUGIN YOU MUST CHANGE Interpreter>>primitiveCalloutToFFI TO REFLECT THE CHANGE." + ^'SqueakFFIPrims (Obsolete)'! - ^'SqueakFFIPrims'! Item was changed: ----- Method: FilePluginSimulator>>sqFileDeleteName:Size: (in category 'simulation') ----- sqFileDeleteName: nameIndex Size: nameSize | path | + path := interpreterProxy asString: nameIndex size: nameSize. - path := interpreterProxy interpreter asString: nameIndex size: nameSize. (StandardFileStream isAFileNamed: path) ifFalse: [^interpreterProxy primitiveFail]. [FileDirectory deleteFilePath: path] on: Error do: [:ex| interpreterProxy primitiveFail]! Item was changed: ----- Method: LargeIntegersPlugin>>cDigitSub:len:with:len:into: (in category 'C core') ----- cDigitSub: pWordSmall len: smallLen with: pWordLarge len: largeLen into: pWordRes | z | <var: #pWordSmall type: #'unsigned int *'> <var: #pWordLarge type: #'unsigned int *'> <var: #pWordRes type: #'unsigned int *'> <var: #z type: #'unsigned long long'> z := 0. 0 to: smallLen - 1 do: [:i | z := z + (self cDigitOf: pWordLarge at: i) - (self cDigitOf: pWordSmall at: i). self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF). + z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])]. - z := 0 - (z >> 63)]. smallLen to: largeLen - 1 do: [:i | z := z + (self cDigitOf: pWordLarge at: i) . self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF). + z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])]. - z := 0 - (z >> 63)]. ^0! Item was changed: ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At: (in category 'memory access') ----- long64At: byteAddress + "memory is a DoubleWordArray, a 64-bit indexable array of bits" - "memory is a DobleWordArray, a 64-bit indexable array of bits" byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError]. ^memory at: byteAddress // 8 + 1! Item was changed: ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At:put: (in category 'memory access') ----- long64At: byteAddress put: a64BitValue + "memory is a DoubleWordArray, a 64-bit indexable array of bits" - "memory is a DobleWordArray, a 64-bit indexable array of bits" byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError]. ^memory at: byteAddress // 8 + 1 put: a64BitValue! Item was changed: ----- Method: Spur64BitMMLESimulatorFor64Bits>>long32At:put: (in category 'memory access') ----- long32At: byteAddress put: a32BitValue "Store the 32-bit word at byteAddress which must be a multiple of four." | lowBits long longAddress | + a32BitValue < 0 ifTrue: + [self long32At: byteAddress put: (a32BitValue bitAnd: 16rFFFFFFFF). + ^a32BitValue]. lowBits := byteAddress bitAnd: 4. lowBits = 0 ifTrue: "storing into LS word" [long := self long64At: byteAddress. self long64At: byteAddress put: ((long bitAnd: 16rFFFFFFFF00000000) bitOr: a32BitValue)] ifFalse: "storing into MS word" [longAddress := byteAddress - 4. long := self long64At: longAddress. self long64At: longAddress put: ((long bitAnd: 16rFFFFFFFF) bitOr: (a32BitValue bitShift: 32))]. ^a32BitValue! Item was changed: ----- Method: Spur64BitMMLESimulatorFor64Bits>>long64At:put: (in category 'memory access') ----- long64At: byteAddress put: a64BitValue + "memory is a DoubleWordArray, a 64-bit indexable array of bits" - "memory is a DobleWordArray, a 64-bit indexable array of bits" byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError]. ^memory at: byteAddress // 8 + 1 put: a64BitValue! Item was added: + ----- Method: SpurMemoryManager>>ISA (in category 'simulation only') ----- + ISA + "hack around the CoInterpreter/ObjectMemory split refactoring" + <doNotGenerate> + ^coInterpreter ISA! Item was added: + ----- Method: SpurMemoryManager>>signed64BitIntegerFor: (in category 'simulation only') ----- + signed64BitIntegerFor: integerValue + "hack around the CoInterpreter/ObjectMemory split refactoring" + <doNotGenerate> + ^coInterpreter signed64BitIntegerFor: integerValue! Item was added: + ----- Method: SpurMemoryManager>>signed64BitValueOf: (in category 'simulation only') ----- + signed64BitValueOf: oop + "hack around the CoInterpreter/ObjectMemory split refactoring" + <doNotGenerate> + ^coInterpreter signed64BitValueOf: oop! Item was added: + ----- Method: SpurMemoryManager>>unalignedLong32At: (in category 'simulation') ----- + unalignedLong32At: index + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + | odd hi lo | + (odd := index bitAnd: 3) = 0 ifTrue: + [^self long32At: index]. + lo := self long32At: index - odd. + hi := self long32At: index + 4 - odd. + ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (4 - odd * 8))! Item was added: + ----- Method: SpurMemoryManager>>unalignedLong32At:put: (in category 'simulation') ----- + unalignedLong32At: index put: aValue + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + | odd hi lo mask | + aValue < 0 ifTrue: + [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFF). + ^aValue]. + (odd := index bitAnd: 3) = 0 ifTrue: + [^self long32At: index put: aValue]. + mask := 1 << (odd * 8) - 1. + lo := self long32At: index - odd. + self long32At: index - odd + put: (lo bitAnd: mask) + + ((aValue bitAnd: 1 << (4 - odd * 8) - 1) << (odd * 8)). + hi := self long32At: index + 4 - odd. + self long32At: index + 4 - odd + put: (hi bitClear: mask) + (aValue >> (4 - odd * 8) bitAnd: mask). + ^aValue! Item was added: + ----- Method: SpurMemoryManager>>unalignedLong64At: (in category 'simulation') ----- + unalignedLong64At: index + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + | odd hi lo | + (odd := index bitAnd: 7) = 0 ifTrue: + [^self long64At: index]. + lo := self long64At: index - odd. + hi := self long64At: index + 8 - odd. + ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (8 - odd * 8))! Item was added: + ----- Method: SpurMemoryManager>>unalignedLong64At:put: (in category 'simulation') ----- + unalignedLong64At: index put: aValue + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + | odd hi lo mask | + aValue < 0 ifTrue: + [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFFFFFFFFFF). + ^aValue]. + (odd := index bitAnd: 7) = 0 ifTrue: + [^self long64At: index put: aValue]. + mask := 1 << (odd * 8) - 1. + lo := self long64At: index - odd. + self long64At: index - odd + put: (lo bitAnd: mask) + + ((aValue bitAnd: 1 << (8 - odd * 8) - 1) << (odd * 8)). + hi := self long64At: index + 8 - odd. + self long64At: index + 8 - odd + put: (hi bitClear: mask) + (aValue >> (8 - odd * 8) bitAnd: mask). + ^aValue! Item was added: + ----- Method: SpurMemoryManager>>unalignedShortAt: (in category 'simulation') ----- + unalignedShortAt: index + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + | hi lo | + (index bitAnd: 1) = 0 ifTrue: + [^self shortAt: index]. + lo := self shortAt: index - 1. + hi := self shortAt: index + 1. + ^lo >> 8 + ((hi bitAnd: 16rFF) << 8)! Item was added: + ----- Method: SpurMemoryManager>>unalignedShortAt:put: (in category 'simulation') ----- + unalignedShortAt: index put: aValue + "Support for primitiveFFIIntegerAt[Put]" + <doNotGenerate> + (index bitAnd: 1) = 0 ifTrue: + [^self shortAt: index put: aValue]. + self shouldBeImplemented. + ^aValue! Item was added: + ----- Method: StackInterpreter>>ISA (in category 'simulation') ----- + ISA + <doNotGenerate> + ^self class initializationOptions + at: #ISA + ifAbsent: [Smalltalk wordSize = 8 + ifTrue: [#X64] + ifFalse: [#IA32]]! Item was changed: ----- Method: StackInterpreter>>ioLoadExternalFunction:OfLength:FromModule:OfLength:AccessorDepthInto: (in category 'primitive support') ----- ioLoadExternalFunction: functionName OfLength: functionLength FromModule: moduleName OfLength: moduleLength AccessorDepthInto: accessorDepthPtr "Load and return the requested function from a module. Assign the accessor depth through accessorDepthPtr. N.B. The actual code lives in platforms/Cross/vm/sqNamedPrims.h" <doNotGenerate> | pluginString functionString | pluginString := String new: moduleLength. + (1 to: moduleLength) do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)]. - 1 to: moduleLength do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)]. functionString := String new: functionLength. + (1 to: functionLength) do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)]. + "We used to ignore loads of the SqueakFFIPrims plugin, but that means doing without integerAt:[put:]size:signed: + which is too much of a limitation (not that these simulate unaligned accesses yet)." - 1 to: functionLength do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)]. - "Pharo images as of 2016 use the FFI plugin (for getenv:?). We can't simulate such function loads. So ignore" - pluginString = 'SqueakFFIPrims' ifTrue: - ["self halt." - true ifTrue: - [self transcript cr; show: 'ignoring function load from SqueakFFIPrims'. - ^0]]. ^self ioLoadFunction: functionString From: pluginString AccessorDepthInto: accessorDepthPtr! Item was changed: ----- Method: ThreadedFFIPlugin class>>preambleCCode (in category 'translation') ----- preambleCCode "For a source of builtin defines grep for builtin_define in a gcc release config directory." ^' #include "sqAssert.h" /* for assert */ #define ThreadedFFIPlugin 1 /* to filter-out unwanted declarations from sqFFI.h */ #include "sqFFI.h" /* for logging and surface functions */ #include "sqCogStackAlignment.h" /* for STACK_ALIGN_BYTES and getsp() */ #ifdef _MSC_VER # define alloca _alloca #endif #if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)) # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp)) # elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64)) # define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp)) # elif defined(__GNUC__) && (defined(__arm__)) # define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp)) #endif #if !!defined(getsp) # define getsp() 0 #endif #if !!defined(setsp) # define setsp(ignored) 0 #endif #if !!defined(STACK_ALIGN_BYTES) # define STACK_ALIGN_BYTES 0 #endif /* !!defined(STACK_ALIGN_BYTES) */ /* For ABI that require stack alignment greater than natural word size */ #define MUST_ALIGN_STACK (STACK_ALIGN_BYTES > sizeof(void*)) #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) /* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size * less than or equal to eight bytes in length in registers. Linux never does so. */ # if __linux__ # define WIN32_X86_STRUCT_RETURN 0 # else # define WIN32_X86_STRUCT_RETURN 1 # endif # if _WIN32 # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1 # endif # elif defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64) # if _WIN32 | _WIN64 # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1 # endif #endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */ #if !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL) # if defined(__MINGW32__) && !!defined(__clang__) && (__GNUC__ >= 3) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)) /* * cygwin -mno-cygwin (MinGW) gcc 3.4.x''s alloca is a library routine that answers * %esp + xx, so the outgoing stack is offset by one or more word if uncorrected. * Grab the actual stack pointer to correct. */ # define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 1 # else # define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 0 # endif #endif /* !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL) */ #if !!defined(PLATFORM_API_USES_CALLEE_POPS_CONVENTION) # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0 #endif + /* This alignment stuff is a hack for integerAt:put:size:signed:/primitiveFFIIntegerAt[Put]. + * The assumption right now is that all processors suppoprt unaligned access. That only + * holds true for x86, x86-64 & ARMv6 & later. But this keeps us going until we can addresws it properly. + */ + #define unalignedShortAt(a) shortAt(a) + #define unalignedShortAtput(a) shortAtput(a) + #define unalignedLong32At(a) long32At(a) + #define unalignedLong32Atput(a) long32Atput(a) + #define unalignedLong64At(a) long64At(a) + #define unalignedLong64Atput(a) long64Atput(a) + /* The dispatchOn:in:with:with: generates an unwanted call on error. Just squash it. */ #define error(foo) 0 #ifndef SQUEAK_BUILTIN_PLUGIN /* but print assert failures. */ void warning(char *s) { /* Print an error message but don''t exit. */ printf("\n%s\n", s); } #endif /* sanitize */ #ifdef SQUEAK_BUILTIN_PLUGIN # define EXTERN #else # define EXTERN extern #endif '! Item was added: + ----- Method: ThreadedFFIPlugin>>initSurfacePluginFunctionPointers (in category 'simulation') ----- + initSurfacePluginFunctionPointers + "This is a simulation-only stub. The real code is in + platforms/Cross/plugins/SqueakFFIPrims/sqManualSurface.c" + <doNotGenerate>! Item was changed: ----- Method: ThreadedFFIPlugin>>initialiseModule (in category 'initialize') ----- initialiseModule <export: true> "By default, disable logging" ffiLogEnabled := false. "Get the instSize of ExternalFunction to know whether it contains a cache of the stackSize, and what the offset of ExternalLibraryFunction's functionName and moduleName slots are." externalFunctionInstSize := interpreterProxy instanceSizeOf: interpreterProxy classExternalFunction. self initSurfacePluginFunctionPointers. + ^true! - ^1! Item was added: + ----- Method: ThreadedFFIPlugin>>morphIntoConcreteSubclass: (in category 'simulation') ----- + morphIntoConcreteSubclass: aCoInterpreter + <doNotGenerate> + | concreteClass | + concreteClass := + aCoInterpreter ISA caseOf: { + [#X64] -> [(Smalltalk platformName beginsWith: 'Win') + ifTrue: [ThreadedX64Win64FFIPlugin] + ifFalse: [ThreadedX64SysVFFIPlugin]]. + [#IA32] -> [ThreadedIA32FFIPlugin]. + [#ARMv5] -> [ThreadedARMFFIPlugin] } + otherwise: [self error: 'simulation not set up for this ISA']. + self changeClassTo: concreteClass! Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAt (in category 'primitives') ----- primitiveFFIIntegerAt "Answer a (signed or unsigned) n byte integer from the given byte offset in the receiver, using the platform's endianness." | isSigned byteSize byteOffset rcvr addr value mask valueOop | <var: 'value' type: #usqLong> <var: 'mask' type: #usqLong> <export: true> <inline: false> isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize := interpreterProxy stackIntegerValue: 1. byteOffset := interpreterProxy stackIntegerValue: 2. rcvr := interpreterProxy stackObjectValue: 3. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and: [(byteSize between: 1 and: 8) and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse: [^interpreterProxy primitiveFail]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. byteSize <= 2 ifTrue: [byteSize = 1 ifTrue: [value := self cCoerceSimple: (interpreterProxy byteAt: addr) to: #'unsigned char'] + ifFalse: [value := self cCoerceSimple: (interpreterProxy unalignedShortAt: addr) to: #'unsigned short']] - ifFalse: [value := self cCoerceSimple: (interpreterProxy shortAt: addr) to: #'unsigned short']] ifFalse: [byteSize = 4 + ifTrue: [value := self cCoerceSimple: (interpreterProxy unalignedLong32At: addr) to: #'unsigned int'] + ifFalse: [value := interpreterProxy unalignedLong64At: addr]]. - ifTrue: [value := self cCoerceSimple: (interpreterProxy long32At: addr) to: #'unsigned int'] - ifFalse: [value := interpreterProxy long64At: addr]]. byteSize < BytesPerWord ifTrue: [isSigned ifTrue: "sign extend value" [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1). value := (value bitAnd: mask-1) - (value bitAnd: mask)]. "note: byte/short (&long if BytesPerWord=8) never exceed SmallInteger range" valueOop := interpreterProxy integerObjectOf: value] ifFalse: "general 64 bit integer; note these never fail" [isSigned ifTrue: [byteSize < 8 ifTrue: "sign extend value" [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1). value := (value bitAnd: mask-1) - (value bitAnd: mask)]. + self cCode: [] inSmalltalk: + [(byteSize = 8 and: [(value bitShift: -56) >= 128]) ifTrue: + [value := value - (1 bitShift: 64)]]. valueOop := interpreterProxy signed64BitIntegerFor: value] ifFalse:[valueOop := interpreterProxy positive64BitIntegerFor: value]]. ^interpreterProxy pop: 4 thenPush: valueOop! Item was changed: ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAtPut (in category 'primitives') ----- primitiveFFIIntegerAtPut "Store a (signed or unsigned) n byte integer at the given byte offset in the receiver, using the platform's endianness." | isSigned byteSize byteOffset rcvr addr value max valueOop | <var: 'value' type: #sqLong> <var: 'max' type: #sqLong> <export: true> <inline: false> isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0). byteSize := interpreterProxy stackIntegerValue: 1. valueOop := interpreterProxy stackValue: 2. byteOffset := interpreterProxy stackIntegerValue: 3. rcvr := interpreterProxy stackObjectValue: 4. interpreterProxy failed ifTrue:[^0]. (byteOffset > 0 and: [(byteSize between: 1 and: 8) and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse: [^interpreterProxy primitiveFail]. addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize. interpreterProxy failed ifTrue:[^0]. isSigned ifTrue:[value := interpreterProxy signed64BitValueOf: valueOop] ifFalse:[value := interpreterProxy positive64BitValueOf: valueOop]. interpreterProxy failed ifTrue:[^0]. byteSize < 8 ifTrue: [isSigned ifTrue: [max := 1 asUnsignedLongLong << (8 * byteSize - 1). (value >= (0 - max) and: [value < max]) ifFalse: [^interpreterProxy primitiveFail]] ifFalse: [value asUnsignedLongLong < (1 asUnsignedLongLong << (8 * byteSize)) ifFalse: [^interpreterProxy primitiveFail]]]. byteSize <= 2 ifTrue: [byteSize = 1 ifTrue: [interpreterProxy byteAt: addr put: value] + ifFalse: [interpreterProxy unalignedShortAt: addr put: value]] - ifFalse: [interpreterProxy shortAt: addr put: value]] ifFalse: [byteSize = 4 + ifTrue: [interpreterProxy unalignedLong32At: addr put: value] + ifFalse: [interpreterProxy unalignedLong64At: addr put: value]]. - ifTrue: [interpreterProxy long32At: addr put: value] - ifFalse: [interpreterProxy long64At: addr put: value]]. ^interpreterProxy pop: 5 thenPush: valueOop! Item was added: + ----- Method: ThreadedFFIPlugin>>setInterpreter: (in category 'simulation') ----- + setInterpreter: anInterpreter + "Initialization of the plugin in the simulator. + The real routine is in the superclass." + self cCode: [] + inSmalltalk: [self class == thisContext method methodClass ifTrue: + [self morphIntoConcreteSubclass: anInterpreter]]. + ^super setInterpreter: anInterpreter! |
Hi Eliot, if we have a certified arithmetic right shift that preserves integer kind - not something like (((usqint) x) >> 32), which is a logical right shift - nor (((sqint) x) >> 32) then what we could do is use a signed long long to store intermediate result: (I call it arithmeticRightShift: because I don't have a VMMaker handy to verify the right name maybe it was >>> ? but then that's the reverse meaning of java!)
<var: #pWordSmall type: #'unsigned int *'> <var: #pWordLarge type: #'unsigned int *'> <var: #pWordRes type: #'unsigned int *'> <var: #z type: #'long long'> z := 0. 0 to: smallLen - 1 do: [:i | z := z + (self cDigitOf: pWordLarge at: i) - (self cDigitOf: pWordSmall at: i). self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
z := z arithmeticRightShift: 32]. smallLen to: largeLen - 1 do: [:i | z := z + (self cDigitOf: pWordLarge at: i). self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
z := z arithmeticRightShift: 32]. ^0! 2017-12-22 6:18 GMT+01:00 <[hidden email]>:
|
Free forum by Nabble | Edit this page |