summaryrefslogtreecommitdiff
path: root/src/luac/opcode.c
blob: c2d4ae7dfc136e4245fc61fdf1d7d2a85d2d41b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
** $Id: opcode.c,v 1.9 1999/05/25 19:58:55 lhf Exp $
** opcode information
** See Copyright Notice in lua.h
*/

#include "luac.h"

enum {					/* for Opcode.args */
 ARGS_NONE,
 ARGS_B,
 ARGS_W,
 ARGS_BB,
 ARGS_WB
};

static Opcode Info[]=			/* ORDER lopcodes.h */
{
#include "opcode.h"
};

static Opcode Fake[]=			/* ORDER luac.h */
{
{ "NOP", NOP, NOP, ARGS_NONE, -1, -1 },
{ "STACK", STACK, STACK, ARGS_B, -1, -1 },
{ "ARGS", ARGS, ARGS, ARGS_B, -1, -1 },
{ "VARARGS", VARARGS, VARARGS, ARGS_B, -1, -1 },
};

#define NOPCODES	(sizeof(Info)/sizeof(Info[0]))

int luaU_opcodeinfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE)
{
 Opcode OP;
 Byte* code=tf->code;
 int op=*p;
 int size=1;
 if (p==code)				/* first byte is STACK */
 {
  OP=Fake[-STACK];
  OP.arg=op;
 }
 else if (p==code+1)			/* second byte is ARGS or VARARGS */
 {
  if (op<ZEROVARARG)
  {
   OP=Fake[-ARGS];
   OP.arg=op;
  }
  else
  {
   OP=Fake[-VARARGS];
   OP.arg=op-ZEROVARARG;
  }
 }
 else if (op==NOP)			/* NOP is fake */
 {
  OP=Fake[0];
 }
 else if (op>=NOPCODES)			/* cannot happen */
 {
  luaL_verror("[%s:%d] bad opcode %d at pc=%d" IN,
	xFILE,xLINE,op,(int)(p-code),INLOC);
  return 0;
 }
 else					/* ordinary opcode */
 {
  OP=Info[op];
  switch (OP.args)
  {
   case ARGS_NONE:	size=1;
    break;
   case ARGS_B:		size=2;	OP.arg=p[1];
    break;
   case ARGS_W:		size=3;	OP.arg=(p[1]<<8)+p[2];
    break;
   case ARGS_BB:	size=3;	OP.arg=p[1];		OP.arg2=p[2];
    break;
   case ARGS_WB:	size=4;	OP.arg=(p[1]<<8)+p[2];	OP.arg2=p[3];
    break;
   default:				/* cannot happen */
    luaL_verror("[%s:%d] bad args %d for %s at pc=%d" IN,
	__FILE__,__LINE__,OP.args,OP.name,(int)(p-code),INLOC);
    break;
  }
 }
 *I=OP;
 return size;
}

int luaU_codesize(TProtoFunc* tf)
{
 Byte* code=tf->code;
 Byte* p=code;
 for (;;)
 {
  Opcode OP;
  p+=INFO(tf,p,&OP);
  if (OP.op==ENDCODE) break;
 }
 return p-code;
}