Open main menu

Difference between revisions of "SCI/Specifications/SCI virtual machine/The Sierra PMachine"

m
Text replacement - "<source lang=" to "<syntaxhighlight lang="
(Fix syntax highlighting)
m (Text replacement - "<source lang=" to "<syntaxhighlight lang=")
Tags: Mobile edit Mobile web edit
Line 59: Line 59:
Certain instructions (in particular, branching ones) take relative addresses as a parameter. The actual address is calculated based on the instruction after the branching instruction itself. In this example, the <tt>bnt</tt> instruction, if the branch is made, jumps over the <tt>ldi</tt> instruction.
Certain instructions (in particular, branching ones) take relative addresses as a parameter. The actual address is calculated based on the instruction after the branching instruction itself. In this example, the <tt>bnt</tt> instruction, if the branch is made, jumps over the <tt>ldi</tt> instruction.


<source lang="asm">
<syntaxhighlight lang="asm">
     eq?
     eq?
     bnt +2
     bnt +2
Line 74: Line 74:
In every call instruction, a value is included which determines the size of the parameter list, as an offset into the stack. This value discounts the list size pushed by the SCI code. For instance, consider this example from real SCI code:
In every call instruction, a value is included which determines the size of the parameter list, as an offset into the stack. This value discounts the list size pushed by the SCI code. For instance, consider this example from real SCI code:


<source lang="asm">
<syntaxhighlight lang="asm">
     pushi 3 ; three parameters passed
     pushi 3 ; three parameters passed
     pushi 4 ; the screen flag
     pushi 4 ; the screen flag
Line 98: Line 98:




<source lang="C">
<syntaxhighlight lang="C">
pop(): sp -= 2; return *sp;
pop(): sp -= 2; return *sp;
push(x): *sp = x; sp += 2; return x;
push(x): *sp = x; sp += 2; return x;
Line 116: Line 116:
;<nowiki>op 0x01: bnot (1 byte)</nowiki>
;<nowiki>op 0x01: bnot (1 byte)</nowiki>
:Binary not
:Binary not
<source lang="C">
<syntaxhighlight lang="C">
acc ^= 0xffff;
acc ^= 0xffff;
</source>
</source>
Line 124: Line 124:
;<nowiki>op 0x03: add (1 byte)</nowiki>
;<nowiki>op 0x03: add (1 byte)</nowiki>
:Addition:
:Addition:
<source lang="C">
<syntaxhighlight lang="C">
acc += pop();
acc += pop();
</source>
</source>
Line 132: Line 132:
;<nowiki>op 0x05: sub (1 byte)</nowiki>
;<nowiki>op 0x05: sub (1 byte)</nowiki>
:Subtraction:
:Subtraction:
<source lang="C">
<syntaxhighlight lang="C">
acc = pop() - acc;
acc = pop() - acc;
</source>
</source>
Line 140: Line 140:
;<nowiki>op 0x07: mul (1 byte)</nowiki>
;<nowiki>op 0x07: mul (1 byte)</nowiki>
:Multiplication:
:Multiplication:
<source lang="C">
<syntaxhighlight lang="C">
acc *= pop();
acc *= pop();
</source>
</source>
Line 148: Line 148:
;<nowiki>op 0x09: div (1 byte)</nowiki>
;<nowiki>op 0x09: div (1 byte)</nowiki>
:Division:
:Division:
<source lang="C">
<syntaxhighlight lang="C">
acc = pop() / acc;
acc = pop() / acc;
</source>
</source>
Line 157: Line 157:
;<nowiki>op 0x0b: mod (1 byte)</nowiki>
;<nowiki>op 0x0b: mod (1 byte)</nowiki>
:Modulo:
:Modulo:
<source lang="C">
<syntaxhighlight lang="C">
acc = pop() % acc;
acc = pop() % acc;
</source>
</source>
Line 166: Line 166:
;<nowiki>op 0x0d: shr (1 byte)</nowiki>
;<nowiki>op 0x0d: shr (1 byte)</nowiki>
:Shift Right logical:
:Shift Right logical:
<source lang="C">
<syntaxhighlight lang="C">
acc = pop() >> acc;
acc = pop() >> acc;
</source>
</source>
Line 174: Line 174:
;<nowiki>op 0x0f: shl (1 byte)</nowiki>
;<nowiki>op 0x0f: shl (1 byte)</nowiki>
:Shift Left logical:
:Shift Left logical:
<source lang="C">
<syntaxhighlight lang="C">
acc = pop() << acc;
acc = pop() << acc;
</source>
</source>
Line 182: Line 182:
;<nowiki>op 0x11: xor (1 byte)</nowiki>
;<nowiki>op 0x11: xor (1 byte)</nowiki>
:Exclusive or:
:Exclusive or:
<source lang="C">
<syntaxhighlight lang="C">
acc ^= pop();
acc ^= pop();
</source>
</source>
Line 190: Line 190:
;<nowiki>op 0x13: and (1 byte)</nowiki>
;<nowiki>op 0x13: and (1 byte)</nowiki>
:Logical and:
:Logical and:
<source lang="C">
<syntaxhighlight lang="C">
acc &= pop();
acc &= pop();
</source>
</source>
Line 198: Line 198:
;<nowiki>op 0x15: or (1 byte)</nowiki>
;<nowiki>op 0x15: or (1 byte)</nowiki>
:Logical or:
:Logical or:
<source lang="C">
<syntaxhighlight lang="C">
acc |= pop();
acc |= pop();
</source>
</source>
Line 206: Line 206:
;<nowiki>op 0x17: neg (1 byte)</nowiki>
;<nowiki>op 0x17: neg (1 byte)</nowiki>
:Sign negation:
:Sign negation:
<source lang="C">
<syntaxhighlight lang="C">
acc = -acc;
acc = -acc;
</source>
</source>
Line 214: Line 214:
;<nowiki>op 0x19: not (1 byte)</nowiki>
;<nowiki>op 0x19: not (1 byte)</nowiki>
:Boolean not:
:Boolean not:
<source lang="C">
<syntaxhighlight lang="C">
acc = !acc;
acc = !acc;
</source>
</source>
Line 222: Line 222:
;<nowiki>op 0x1b: eq? (1 byte)</nowiki>
;<nowiki>op 0x1b: eq? (1 byte)</nowiki>
:Equals?:
:Equals?:
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = (acc == pop());
acc = (acc == pop());
Line 231: Line 231:
;<nowiki>op 0x1d: ne? (1 byte)</nowiki>
;<nowiki>op 0x1d: ne? (1 byte)</nowiki>
:Is not equal to?
:Is not equal to?
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = !(acc == pop());
acc = !(acc == pop());
Line 240: Line 240:
;<nowiki>op 0x1f: gt? (1 byte)</nowiki>
;<nowiki>op 0x1f: gt? (1 byte)</nowiki>
:Greater than?
:Greater than?
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = (pop() > acc);
acc = (pop() > acc);
Line 249: Line 249:
;<nowiki>op 0x21: ge? (1 byte)</nowiki>
;<nowiki>op 0x21: ge? (1 byte)</nowiki>
:Greater than or equal to?
:Greater than or equal to?
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = (pop() >= acc);
acc = (pop() >= acc);
Line 258: Line 258:
;<nowiki>op 0x23: lt? (1 byte)</nowiki>
;<nowiki>op 0x23: lt? (1 byte)</nowiki>
:Less than?
:Less than?
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = (pop() < acc);
acc = (pop() < acc);
Line 267: Line 267:
;<nowiki>op 0x25: le? (1 byte)</nowiki>
;<nowiki>op 0x25: le? (1 byte)</nowiki>
:Less than or equal to?
:Less than or equal to?
<source lang="C">
<syntaxhighlight lang="C">
prev = acc;
prev = acc;
acc = (pop() <= acc);
acc = (pop() <= acc);
Line 276: Line 276:
;<nowiki>op 0x27: ugt? (1 byte)</nowiki>
;<nowiki>op 0x27: ugt? (1 byte)</nowiki>
:Unsigned: Greater than?
:Unsigned: Greater than?
<source lang="C">
<syntaxhighlight lang="C">
acc = (pop() > acc);
acc = (pop() > acc);
</source>
</source>
Line 284: Line 284:
;<nowiki>op 0x29: uge? (1 byte)</nowiki>
;<nowiki>op 0x29: uge? (1 byte)</nowiki>
:Unsigned: Greather than or equal to?
:Unsigned: Greather than or equal to?
<source lang="C">
<syntaxhighlight lang="C">
acc = (pop() >= acc);
acc = (pop() >= acc);
</source>
</source>
Line 292: Line 292:
;<nowiki>op 0x2b: ult? (1 byte)</nowiki>
;<nowiki>op 0x2b: ult? (1 byte)</nowiki>
:Unsigned: Less than?
:Unsigned: Less than?
<source lang="C">
<syntaxhighlight lang="C">
acc = (pop() < acc);
acc = (pop() < acc);
</source>
</source>
Line 300: Line 300:
;<nowiki>op 0x2d: ule? (1 byte)</nowiki>
;<nowiki>op 0x2d: ule? (1 byte)</nowiki>
:Unsigned: Less than or equal to?
:Unsigned: Less than or equal to?
<source lang="C">
<syntaxhighlight lang="C">
acc = (pop() >= acc);
acc = (pop() >= acc);
</source>
</source>
Line 308: Line 308:
;<nowiki>op 0x2f: bt B relpos (2 bytes)</nowiki>
;<nowiki>op 0x2f: bt B relpos (2 bytes)</nowiki>
:Branch relative if true
:Branch relative if true
<source lang="C">
<syntaxhighlight lang="C">
if (acc) pc += relpos;
if (acc) pc += relpos;
</source>
</source>
Line 316: Line 316:
;<nowiki>op 0x31: bnt B relpos (2 bytes)</nowiki>
;<nowiki>op 0x31: bnt B relpos (2 bytes)</nowiki>
:Branch relative if not true
:Branch relative if not true
<source lang="C">
<syntaxhighlight lang="C">
if (!acc) pc += relpos;
if (!acc) pc += relpos;
</source>
</source>
Line 324: Line 324:
;<nowiki>op 0x33: jmp B relpos (2 bytes)</nowiki>
;<nowiki>op 0x33: jmp B relpos (2 bytes)</nowiki>
:Jump
:Jump
<source lang="C">
<syntaxhighlight lang="C">
pc += relpos;
pc += relpos;
</source>
</source>
Line 332: Line 332:
;<nowiki>op 0x35: ldi B data (2 bytes)</nowiki>
;<nowiki>op 0x35: ldi B data (2 bytes)</nowiki>
:Load data immediate
:Load data immediate
<source lang="C">
<syntaxhighlight lang="C">
acc = data;
acc = data;
</source>
</source>
Line 341: Line 341:
;<nowiki>op 0x37: push (1 byte)</nowiki>
;<nowiki>op 0x37: push (1 byte)</nowiki>
:Push to stack
:Push to stack
<source lang="C">
<syntaxhighlight lang="C">
push(acc)
push(acc)
</source>
</source>
Line 349: Line 349:
;<nowiki>op 0x39: pushi B data (2 bytes)</nowiki>
;<nowiki>op 0x39: pushi B data (2 bytes)</nowiki>
:Push immediate
:Push immediate
<source lang="C">
<syntaxhighlight lang="C">
push(data)
push(data)
</source>
</source>
Line 358: Line 358:
;<nowiki>op 0x3b: toss (1 byte)</nowiki>
;<nowiki>op 0x3b: toss (1 byte)</nowiki>
:TOS subtract
:TOS subtract
<source lang="C">
<syntaxhighlight lang="C">
pop();
pop();
</source>
</source>
Line 367: Line 367:
;<nowiki>op 0x3d: dup (1 byte)</nowiki>
;<nowiki>op 0x3d: dup (1 byte)</nowiki>
:Duplicate TOS element
:Duplicate TOS element
<source lang="C">
<syntaxhighlight lang="C">
push(*TOS);
push(*TOS);
</source>
</source>
Line 374: Line 374:
;<nowiki>op 0x3e: link W size (3 bytes)</nowiki>
;<nowiki>op 0x3e: link W size (3 bytes)</nowiki>
;<nowiki>op 0x3f: link B size (2 bytes)</nowiki>
;<nowiki>op 0x3f: link B size (2 bytes)</nowiki>
<source lang="C">
<syntaxhighlight lang="C">
sp += (size * 2);
sp += (size * 2);
</source>
</source>
Line 383: Line 383:
:Call inside script.
:Call inside script.
:(See description below)
:(See description below)
<source lang="C">
<syntaxhighlight lang="C">
sp -= (framesize + 2 + &rest_modifier);
sp -= (framesize + 2 + &rest_modifier);
&rest_modifier = 0;
&rest_modifier = 0;
Line 394: Line 394:
;<nowiki>op 0x43: callk B kfunct, B kparams (3 bytes)</nowiki>
;<nowiki>op 0x43: callk B kfunct, B kparams (3 bytes)</nowiki>
:Call kernel function (see the [[SCI/Specifications/SCI virtual machine/Kernel functions|Kernel functions]] section)
:Call kernel function (see the [[SCI/Specifications/SCI virtual machine/Kernel functions|Kernel functions]] section)
<source lang="C">
<syntaxhighlight lang="C">
sp -= (kparams + 2 + &rest_modifier);
sp -= (kparams + 2 + &rest_modifier);
&rest_modifier = 0;
&rest_modifier = 0;
Line 405: Line 405:
:Call base script
:Call base script
:(See description below)
:(See description below)
<source lang="C">
<syntaxhighlight lang="C">
sp -= (framesize + 2 + &rest_modifier);
sp -= (framesize + 2 + &rest_modifier);
&rest_modifier = 0;
&rest_modifier = 0;
Line 416: Line 416:
:Call external script
:Call external script
:(See description below)
:(See description below)
<source lang="C">
<syntaxhighlight lang="C">
sp -= (framesize + 2 + &rest_modifier);
sp -= (framesize + 2 + &rest_modifier);
&rest_modifier = 0;
&rest_modifier = 0;
Line 434: Line 434:
:Send looks up the supplied selector(s) in the object pointed to by the accumulator. If the selector is a variable selector, it is read (to the accumulator) if it was sent for with zero parameters. If a parameter was supplied, this selector is set to that parameter. Method selectors are called with the specified parameters.
:Send looks up the supplied selector(s) in the object pointed to by the accumulator. If the selector is a variable selector, it is read (to the accumulator) if it was sent for with zero parameters. If a parameter was supplied, this selector is set to that parameter. Method selectors are called with the specified parameters.
:The selector(s) and parameters are retreived from the stack frame. Send first looks up the selector ID at the bottom of the frame, then retreives the number of parameters, and, eventually, the parameters themselves. This algorithm is iterated until all of the stack frame has been "used up". Example:
:The selector(s) and parameters are retreived from the stack frame. Send first looks up the selector ID at the bottom of the frame, then retreives the number of parameters, and, eventually, the parameters themselves. This algorithm is iterated until all of the stack frame has been "used up". Example:
<source lang="asm">
<syntaxhighlight lang="asm">
; This is an example for usage of the SCI send operation
; This is an example for usage of the SCI send operation
   pushi x      ; push the selector ID of x
   pushi x      ; push the selector ID of x
Line 504: Line 504:
::set if the accumulator is to be used as additional index  
::set if the accumulator is to be used as additional index  
:::Because it is so hard to explain, I have made a transcription of it here:
:::Because it is so hard to explain, I have made a transcription of it here:
<source lang="C">
<syntaxhighlight lang="C">
short *vars[4];
short *vars[4];


Line 519: Line 519:
;<nowiki>op 0x5d: selfID (1 bytes)</nowiki>
;<nowiki>op 0x5d: selfID (1 bytes)</nowiki>
:Get 'self' identity: SCI uses heap pointers to identify objects, so this operation sets the accumulator to the address of the current object.
:Get 'self' identity: SCI uses heap pointers to identify objects, so this operation sets the accumulator to the address of the current object.
<source lang="C">acc = object</source>
<syntaxhighlight lang="C">acc = object</source>




Line 530: Line 530:
;<nowiki>op 0x61: pprev (1 bytes)</nowiki>
;<nowiki>op 0x61: pprev (1 bytes)</nowiki>
:Push prev: Pushes the value of the prev register, set by the last comparison bytecode (eq?, lt?, etc.), on the stack.
:Push prev: Pushes the value of the prev register, set by the last comparison bytecode (eq?, lt?, etc.), on the stack.
<source lang="C">push(prev)</source>
<syntaxhighlight lang="C">push(prev)</source>




Line 576: Line 576:
;<nowiki>op 0x73: lofsa B offset (2 bytes)</nowiki>
;<nowiki>op 0x73: lofsa B offset (2 bytes)</nowiki>
:Load Offset to Accumulator:
:Load Offset to Accumulator:
<source lang="C">acc = pc + offset</source>
<syntaxhighlight lang="C">acc = pc + offset</source>
:Adds a value to the post-operation pc and stores the result in the accumulator.
:Adds a value to the post-operation pc and stores the result in the accumulator.


Line 583: Line 583:
;<nowiki>op 0x75: lofss B offset (2 bytes)</nowiki>
;<nowiki>op 0x75: lofss B offset (2 bytes)</nowiki>
:Load Offset to Stack:
:Load Offset to Stack:
<source lang="C">push(pc + offset)</source>
<syntaxhighlight lang="C">push(pc + offset)</source>
:Adds a value to the post-operation pc and pushes the result on the stack.
:Adds a value to the post-operation pc and pushes the result on the stack.


Line 590: Line 590:
;<nowiki>op 0x77: push0 (1 bytes)</nowiki>
;<nowiki>op 0x77: push0 (1 bytes)</nowiki>
:Push 0:
:Push 0:
<source lang="C">push(0)</source>
<syntaxhighlight lang="C">push(0)</source>




Line 596: Line 596:
;<nowiki>op 0x79: push1 (1 bytes)</nowiki>
;<nowiki>op 0x79: push1 (1 bytes)</nowiki>
:Push 1:
:Push 1:
<source lang="C">push(1)</source>
<syntaxhighlight lang="C">push(1)</source>




Line 602: Line 602:
;<nowiki>op 0x7b: push2 (1 bytes)</nowiki>
;<nowiki>op 0x7b: push2 (1 bytes)</nowiki>
:Push 2:
:Push 2:
<source lang="C">push(2)</source>
<syntaxhighlight lang="C">push(2)</source>




Line 608: Line 608:
;<nowiki>op 0x7d: pushSelf (1 bytes)</nowiki>
;<nowiki>op 0x7d: pushSelf (1 bytes)</nowiki>
:Push self:
:Push self:
<source lang="C">push(object)</source>
<syntaxhighlight lang="C">push(object)</source>




TrustedUser
2,147

edits