зеркало из https://github.com/mozilla/pjs.git
more arithmetic, conditional branches, return instruction.
This commit is contained in:
Родитель
a57994c317
Коммит
602bdc5282
|
@ -35,9 +35,16 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
JSValues registers(32);
|
JSValues registers(32);
|
||||||
static std::map<String, JSValue> globals;
|
static std::map<String, JSValue> globals;
|
||||||
|
|
||||||
for (InstructionIterator pc = iCode.begin(); pc != iCode.end(); ++pc) {
|
InstructionIterator pc = iCode.begin();
|
||||||
|
while (pc != iCode.end()) {
|
||||||
Instruction* instruction = *pc;
|
Instruction* instruction = *pc;
|
||||||
switch (instruction->opcode()) {
|
switch (instruction->opcode()) {
|
||||||
|
case MOVE_TO:
|
||||||
|
{
|
||||||
|
Move* i = static_cast<Move*>(instruction);
|
||||||
|
registers[op2(i)] = registers[op1(i)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
case LOAD_NAME:
|
case LOAD_NAME:
|
||||||
{
|
{
|
||||||
LoadName* i = static_cast<LoadName*>(instruction);
|
LoadName* i = static_cast<LoadName*>(instruction);
|
||||||
|
@ -72,14 +79,61 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
{
|
{
|
||||||
Branch* i = static_cast<Branch*>(instruction);
|
Branch* i = static_cast<Branch*>(instruction);
|
||||||
pc = iCode.begin() + op1(i);
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BRANCH_COND:
|
case BRANCH_LT:
|
||||||
{
|
{
|
||||||
BranchCond* i = static_cast<BranchCond*>(instruction);
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
// s << "target #" << t->itsOperand1 << ", R" << t->itsOperand2;
|
if (registers[op2(i)].i32 < 0) {
|
||||||
if (registers[op2(i)].i32)
|
|
||||||
pc = iCode.begin() + op1(i);
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_LE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 <= 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_EQ:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 == 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_NE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 != 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_GE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 >= 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_GT:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 > 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ADD:
|
case ADD:
|
||||||
|
@ -89,16 +143,32 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
registers[op3(i)] = JSValue(registers[op1(i)].f64 + registers[op2(i)].f64);
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 + registers[op2(i)].f64);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 - registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 * registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 / registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case COMPARE:
|
case COMPARE:
|
||||||
{
|
{
|
||||||
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
registers[op3(i)].i32 = registers[op1(i)].f64 == registers[op2(i)].f64;
|
float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64);
|
||||||
}
|
registers[op3(i)].i32 = (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1));
|
||||||
break;
|
|
||||||
case MOVE_TO:
|
|
||||||
{
|
|
||||||
Move* i = static_cast<Move*>(instruction);
|
|
||||||
registers[op2(i)] = registers[op1(i)];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NOT:
|
case NOT:
|
||||||
|
@ -107,9 +177,19 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
registers[op2(i)].i32 = !registers[op1(i)].i32;
|
registers[op2(i)].i32 = !registers[op1(i)].i32;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case RETURN:
|
||||||
|
{
|
||||||
|
Return* i = static_cast<Return*>(instruction);
|
||||||
|
result = registers[op1(i)];
|
||||||
|
pc = iCode.end();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increment the program counter.
|
||||||
|
++pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -35,9 +35,16 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
JSValues registers(32);
|
JSValues registers(32);
|
||||||
static std::map<String, JSValue> globals;
|
static std::map<String, JSValue> globals;
|
||||||
|
|
||||||
for (InstructionIterator pc = iCode.begin(); pc != iCode.end(); ++pc) {
|
InstructionIterator pc = iCode.begin();
|
||||||
|
while (pc != iCode.end()) {
|
||||||
Instruction* instruction = *pc;
|
Instruction* instruction = *pc;
|
||||||
switch (instruction->opcode()) {
|
switch (instruction->opcode()) {
|
||||||
|
case MOVE_TO:
|
||||||
|
{
|
||||||
|
Move* i = static_cast<Move*>(instruction);
|
||||||
|
registers[op2(i)] = registers[op1(i)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
case LOAD_NAME:
|
case LOAD_NAME:
|
||||||
{
|
{
|
||||||
LoadName* i = static_cast<LoadName*>(instruction);
|
LoadName* i = static_cast<LoadName*>(instruction);
|
||||||
|
@ -72,14 +79,61 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
{
|
{
|
||||||
Branch* i = static_cast<Branch*>(instruction);
|
Branch* i = static_cast<Branch*>(instruction);
|
||||||
pc = iCode.begin() + op1(i);
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BRANCH_COND:
|
case BRANCH_LT:
|
||||||
{
|
{
|
||||||
BranchCond* i = static_cast<BranchCond*>(instruction);
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
// s << "target #" << t->itsOperand1 << ", R" << t->itsOperand2;
|
if (registers[op2(i)].i32 < 0) {
|
||||||
if (registers[op2(i)].i32)
|
|
||||||
pc = iCode.begin() + op1(i);
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_LE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 <= 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_EQ:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 == 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_NE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 != 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_GE:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 >= 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BRANCH_GT:
|
||||||
|
{
|
||||||
|
BranchCond* i = static_cast<BranchCond*>(instruction);
|
||||||
|
if (registers[op2(i)].i32 > 0) {
|
||||||
|
pc = iCode.begin() + op1(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ADD:
|
case ADD:
|
||||||
|
@ -89,16 +143,32 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
registers[op3(i)] = JSValue(registers[op1(i)].f64 + registers[op2(i)].f64);
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 + registers[op2(i)].f64);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SUBTRACT:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 - registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MULTIPLY:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 * registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIVIDE:
|
||||||
|
{
|
||||||
|
// could get clever here with Functional forms.
|
||||||
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
|
registers[op3(i)] = JSValue(registers[op1(i)].f64 / registers[op2(i)].f64);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case COMPARE:
|
case COMPARE:
|
||||||
{
|
{
|
||||||
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
Arithmetic* i = static_cast<Arithmetic*>(instruction);
|
||||||
registers[op3(i)].i32 = registers[op1(i)].f64 == registers[op2(i)].f64;
|
float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64);
|
||||||
}
|
registers[op3(i)].i32 = (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1));
|
||||||
break;
|
|
||||||
case MOVE_TO:
|
|
||||||
{
|
|
||||||
Move* i = static_cast<Move*>(instruction);
|
|
||||||
registers[op2(i)] = registers[op1(i)];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NOT:
|
case NOT:
|
||||||
|
@ -107,9 +177,19 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args)
|
||||||
registers[op2(i)].i32 = !registers[op1(i)].i32;
|
registers[op2(i)].i32 = !registers[op1(i)].i32;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case RETURN:
|
||||||
|
{
|
||||||
|
Return* i = static_cast<Return*>(instruction);
|
||||||
|
result = registers[op1(i)];
|
||||||
|
pc = iCode.end();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increment the program counter.
|
||||||
|
++pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче