mcst-linux-kernel/patches-2024.06.26/luajit-2.1.0/files/tutorial.c

217 lines
5.0 KiB
C

/* Copyright (c) 2020-2024 AO MCST
* Distributed under the terms of MIT License.
*/
#include <stdio.h>
#include <stdlib.h>
#include "dynasm/dasm_proto.h"
#include "dynasm/dasm_e2k.h"
#include <sys/mman.h>
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
static void* link_and_encode(dasm_State** d)
{
size_t sz;
void* buf;
dasm_link(d, &sz);
buf = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
dasm_encode(d, buf);
mprotect(buf, sz, PROT_READ | PROT_EXEC);
return buf;
}
#define TAPE_SIZE 30000
#define MAX_NESTING 100
typedef struct bf_state
{
unsigned char* tape;
unsigned char (*get_ch)(struct bf_state*);
void (*put_ch)(struct bf_state*, unsigned char);
} bf_state_t;
#define bad_program(s) exit(fprintf(stderr, "bad program near %.16s: %s\n", program, s))
static void(* bf_compile(const char* program) )(bf_state_t*)
{
unsigned loops[MAX_NESTING];
int nloops = 0;
int n;
dasm_State* d;
unsigned npc = 8;
unsigned nextpc = 0;
|.arch e2k
|.section code
dasm_init(&d, DASM_MAXSECTION);
|.globals lbl_
void* labels[lbl__MAX];
dasm_setupglobal(&d, labels, lbl__MAX);
|.actionlist bf_actions
dasm_setup(&d, bf_actions);
dasm_growpc(&d, npc);
|.define rArg1, r0
|.define rTmp1, r1
|.define aPtr, r2
|.define aState, r3
|.define aTapeBegin, r4
|.define aTapeEnd, r5
|.define cArg1, b0
|.define cArg2, b1
|.define cRet1, rArg1
|.type state, bf_state_t
dasm_State** Dst = &d;
|.code
|->bf_main:
|<
| setwd wsz = 0x8, nfx = 0x1, dbl = 0x0
| setbn rsz = 0x3, rbs = 0x4, rcur = 0x0
| ldd 0, rArg1, state->tape, aPtr
| addd 1, rArg1, 0x0, aState
|>
|<
| subd 0, aPtr, 0x1, aTapeBegin
| addd 1, aPtr, TAPE_SIZE-1, aTapeEnd
|>
for(;;) {
switch(*program++) {
case '<':
for(n = 1; *program == '<'; ++n, ++program);
|<
| disp ctpr1, >1
| subd 0, aPtr, n%TAPE_SIZE, aPtr
|>
| cmpbedb 0, aPtr, aTapeBegin, pred0
| addd 0, aPtr, TAPE_SIZE, aPtr, pred0
break;
case '>':
for(n = 1; *program == '>'; ++n, ++program);
|<
| disp ctpr1, >1
| addd 0, aPtr, n%TAPE_SIZE, aPtr
|>
| cmpbedb 0, aPtr, aTapeEnd, pred0
| subd 0, aPtr, TAPE_SIZE, aPtr, ~pred0
break;
case '+':
for(n = 1; *program == '+'; ++n, ++program);
| ldb 0, aPtr, 0x0, rTmp1
| addd 0, rTmp1, n, rTmp1
| stb 2, aPtr, 0x0, rTmp1
break;
case '-':
for(n = 1; *program == '-'; ++n, ++program);
| ldb 0, aPtr, 0x0, rTmp1
| subd 0, rTmp1, n, rTmp1
| stb 2, aPtr, 0x0, rTmp1
break;
case ',':
|<
| addd 0, aState, 0x0, cArg1
| ldd 2, aState, state->get_ch, rTmp1
|>
| movtd 0, rTmp1, ctpr1
| call ctpr1, wbs = 0x4
| stb 2, aPtr, 0x0, cRet1
break;
case '.':
|<
| ldb 0, aPtr, 0x0, cArg2
| addd 1, aState, 0x0, cArg1
| ldd 2, aState, state->put_ch, rTmp1
|>
| movtd 0, rTmp1, ctpr1
| call ctpr1, wbs = 0x4
break;
case '[':
if(nloops == MAX_NESTING)
bad_program("Nesting too deep");
if(program[0] == '-' && program[1] == ']') {
program += 2;
| addd 0, 0x0, 0x0, rTmp1
| stb 2, aPtr, 0x0, rTmp1
} else {
if(nextpc == npc) {
npc *= 2;
dasm_growpc(&d, npc);
}
|<
| disp ctpr1, =>nextpc+1
| ldb 0, aPtr, 0x0, rTmp1
|>
| cmpedb 0, rTmp1, 0x0, pred0
| ct ctpr1, pred0
|=>nextpc:
loops[nloops++] = nextpc;
nextpc += 2;
}
break;
case ']':
if(nloops == 0)
bad_program("] without matching [");
--nloops;
|<
| disp ctpr1, =>loops[nloops]
| ldb 0, aPtr, 0x0, rTmp1
|>
| cmpedb 0, rTmp1, 0x0, pred0
| ct ctpr1, ~pred0
|=>loops[nloops]+1:
break;
case 0:
if(nloops != 0)
program = "<EOF>", bad_program("[ without matching ]");
| return ctpr3
| ct ctpr3
link_and_encode(&d);
dasm_free(&d);
return (void(*)(bf_state_t*))labels[lbl_bf_main];
}
}
}
static void bf_putchar(bf_state_t* s, unsigned char c)
{
putchar((int)c);
}
static unsigned char bf_getchar(bf_state_t* s)
{
return (unsigned char)getchar();
}
static void bf_run(const char* program)
{
bf_state_t state;
unsigned char tape[TAPE_SIZE] = {0};
state.tape = tape;
state.get_ch = bf_getchar;
state.put_ch = bf_putchar;
bf_compile(program)(&state);
}
int main(int argc, char** argv)
{
if(argc == 2) {
long sz;
char* program;
FILE* f = fopen(argv[1], "r");
if(!f) {
fprintf(stderr, "Cannot open %s\n", argv[1]);
return 1;
}
fseek(f, 0, SEEK_END);
sz = ftell(f);
program = (char*)malloc(sz + 1);
fseek(f, 0, SEEK_SET);
program[fread(program, 1, sz, f)] = 0;
fclose(f);
bf_run(program);
return 0;
} else {
fprintf(stderr, "Usage: %s INFILE.bf\n", argv[0]);
return 1;
}
}