<br><br><div class="gmail_quote">On Tue, May 10, 2011 at 11:11 PM, Nicolas Cellier <span dir="ltr"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
With a single API, when one will implement another processor<br>
instruction set, you'll win.<br>
The naming of registers is application dependent, but these are just constants.<br>
I wonder if Eliot gave a look at gcc?<br></blockquote><div><br></div><div>Not really. My naming is based on a) the approach to registers Peter Deutsch invented for HPS, the VisualWorks VM, which supports an acceptably efficient register-based calling convention for Smalltalk machine code, and b) the x86 ABI which determines which registers are callee-saved, caller-saved, scratch and the C result register. One shouldn't consider the register names used in the Cog JIT as general names; they're specific to the calling convention implemented by the Cog JIT for Smalltalk execution.</div>
<div><br></div><div>HTH,</div><div>Eliot</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Nicolas<br>
<br>
2011/5/11 Igor Stasenko <<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>>:<br>
<div><div></div><div class="h5">> Hi,<br>
><br>
> i took a look at Cog's abstract opcode syntax.<br>
> Check the CogRTLOpcodes class>>initialize for description,<br>
> and check the Cogit category 'abstract instructions' at instance side<br>
> for actual syntax.<br>
><br>
> Things i don't like: register naming.<br>
> In cog you should use following register names:<br>
> FPReg := -1.<br>
> SPReg := -2.<br>
> ReceiverResultReg := GPRegMax := -3.<br>
> TempReg := -4.<br>
> ClassReg := -5.<br>
> SendNumArgsReg := -6.<br>
> Arg0Reg := -7.<br>
> Arg1Reg := GPRegMin := -8.<br>
> DPFPReg0 := -9.<br>
> DPFPReg1 := -10.<br>
> DPFPReg2 := -11.<br>
> DPFPReg3 := -12.<br>
> DPFPReg4 := -13.<br>
> DPFPReg5 := -14.<br>
> DPFPReg6 := -15.<br>
> DPFPReg7 := -16.<br>
><br>
> They are mapping 1:1 to real registers on your machine.<br>
> But while such names could make sense in some cases for Cog,<br>
> in NativeBoost using register named like SendNumArgsReg will be confusing..<br>
> Okay... actually this is not a big deal, i could always use aliases<br>
> with different names (suggestions?).<br>
><br>
> But i would really like you opinion on Cog's native code syntax.<br>
> Here how the native code assembly looks in cog:<br>
><br>
> genDoubleArithmetic: arithmeticOperator preOpCheck: preOpCheckOrNil<br>
> "Receiver and arg in registers.<br>
> Stack looks like<br>
> return address"<br>
> <var: #preOpCheckOrNil declareC: 'AbstractInstruction<br>
> *(*preOpCheckOrNil)(int rcvrReg, int argReg)'><br>
> | jumpFailClass jumpFailAlloc jumpFailCheck jumpSmallInt doOp |<br>
> <var: #jumpFailClass type: #'AbstractInstruction *'><br>
> <var: #jumpFailAlloc type: #'AbstractInstruction *'><br>
> <var: #jumpSmallInt type: #'AbstractInstruction *'><br>
> <var: #jumpFailCheck type: #'AbstractInstruction *'><br>
> <var: #doOp type: #'AbstractInstruction *'><br>
> self MoveR: Arg0Reg R: TempReg.<br>
> objectRepresentation genGetDoubleValueOf: ReceiverResultReg into: DPFPReg0.<br>
> self MoveR: Arg0Reg R: ClassReg.<br>
> jumpSmallInt := objectRepresentation genJumpSmallIntegerInScratchReg: TempReg.<br>
> objectRepresentation genGetCompactClassIndexNonIntOf: Arg0Reg into:<br>
> SendNumArgsReg.<br>
> self CmpCq: objectMemory classFloatCompactIndex R: SendNumArgsReg.<br>
> jumpFailClass := self JumpNonZero: 0.<br>
> objectRepresentation genGetDoubleValueOf: Arg0Reg into: DPFPReg1.<br>
> doOp := self Label.<br>
> preOpCheckOrNil ifNotNil:<br>
> [jumpFailCheck := self perform: preOpCheckOrNil with: DPFPReg0 with:<br>
> DPFPReg1].<br>
> self gen: arithmeticOperator operand: DPFPReg1 operand: DPFPReg0.<br>
> jumpFailAlloc := objectRepresentation<br>
> genAllocFloatValue: DPFPReg0<br>
> into: SendNumArgsReg<br>
> scratchReg: ClassReg<br>
> scratchReg: TempReg.<br>
> self MoveR: SendNumArgsReg R: ReceiverResultReg.<br>
> self RetN: 0.<br>
> "We need to push the register args on two paths; this one and the<br>
> interpreter primitive path.<br>
> But the interpreter primitive path won't unless regArgsHaveBeenPushed<br>
> is false."<br>
> self assert: methodOrBlockNumArgs <= self numRegArgs.<br>
> jumpFailClass jmpTarget: self Label.<br>
> preOpCheckOrNil ifNotNil:<br>
> [jumpFailCheck jmpTarget: jumpFailClass getJmpTarget].<br>
> self genPushRegisterArgsForNumArgs: methodOrBlockNumArgs.<br>
> jumpFailClass := self Jump: 0.<br>
> jumpSmallInt jmpTarget: self Label.<br>
> objectRepresentation genConvertSmallIntegerToIntegerInScratchReg: ClassReg.<br>
> self ConvertR: ClassReg Rd: DPFPReg1.<br>
> self Jump: doOp.<br>
> jumpFailAlloc jmpTarget: self Label.<br>
> self compileInterpreterPrimitive: (coInterpreter<br>
> functionPointerForCompiledMethod: methodObj<br>
> primitiveIndex: primitiveIndex).<br>
> jumpFailClass jmpTarget: self Label.<br>
> ^0<br>
><br>
> And here an example of NativeBoost code:<br>
><br>
> emitArgumentsCoercion: gen<br>
> " input - none,<br>
> output - an arguments array in remmappable oops stack top"<br>
> | asm proxy args argOop i |<br>
> asm := gen asm.<br>
> proxy := gen proxy.<br>
> args := gen reserveTemp.<br>
> argOop := gen reserveTemp.<br>
><br>
> asm label: 'emitArgumentsCoercion>>'.<br>
><br>
> proxy createInstanceOf: Array size: (gen fnSpec arguments size).<br>
> proxy pushRemappableOop: EAX.<br>
><br>
> i := 0.<br>
> gen fnSpec arguments do: [:arg |<br>
> arg type readOop: (EBP ptr + arg offset) generator: gen.<br>
> asm mov: EAX to: argOop.<br>
> proxy popRemappableOop.<br>
> asm mov: EAX to: args.<br>
> proxy storePointer: i ofObject: args withValue: argOop.<br>
> i := i+1.<br>
> proxy pushRemappableOop: args.<br>
> ].<br>
><br>
> asm label: '<<emitArgumentsCoercion'.<br>
><br>
> gen releaseTemps: 2.<br>
><br>
> The code is of course doing different things.. but these example is<br>
> actually to indicate a following observation:<br>
><br>
> even when i will introduce platform-neutral code, in most cases<br>
> you won't see a pure assembly language, but instead you will see a mix<br>
> of usual smalltalk code and assembler.<br>
><br>
> If you can see, in both examples above you see a direct instructions<br>
> intermixed with another methods.<br>
> And it is totally normal, because for obvious reasons, even for<br>
> assembler code, there are a lot of repetitious patterns,<br>
> and you refactor repetitive code into separate methods (a thing which<br>
> you normally do if you follow DRY principle).<br>
><br>
> So, i mean: its okay. I could change the assembler syntax to anything.<br>
> But code will still be looking mostly the same,<br>
> for most of code-generation routines.<br>
> Of course, if you write a pure-assembly routine, it will be pure. But<br>
> in practice you won't do it too often,<br>
> because you can reuse stuff which already been done, or even use<br>
> higher-level abstract syntax (i have one somewhere in my garage ;).<br>
><br>
> But still, question remains open: should i take a Cog's assembler<br>
> syntax as a base,<br>
> or create own?<br>
> The pro for Cog-syntax that if some day we move code generation from<br>
> VM level to language,<br>
> then we can just use existing code.<br>
><br>
> But from another side, if i have tool which can produce a native code,<br>
> from VM's perspective its completely irrelevant , where this code<br>
> comes from and what assembler syntax were used to generate it.<br>
><br>
> Also, we don't have to constrain ourselves, because Cog's assembler<br>
> (and its implementation) were designed by taking into account that it<br>
> should be translatable to C,<br>
> while in NB we're always could use tricks like #perform: and block<br>
> closures, which of course not available in slang.<br>
><br>
> Sorry for long tiresome posts.. But i need your feedback and opinion.<br>
><br>
> --<br>
> Best regards,<br>
> Igor Stasenko AKA sig.<br>
><br>
><br>
<br>
</div></div></blockquote></div><br>