mirror of https://github.com/Nonannet/copapy.git
test
This commit is contained in:
parent
23be1b1cae
commit
59f3b162de
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
objdump -D -b binary -m i386:x86-64 --adjust-vma=0x1000 bin/test_code.bin
|
||||
|
|
@ -354,7 +354,6 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database
|
|||
|
||||
for variable in variable_list:
|
||||
lengths = sdb.var_size['dummy_' + variable.dtype]
|
||||
print('variable_mem_layout', variable.dtype, lengths)
|
||||
object_list.append((variable, offset, lengths))
|
||||
offset += (lengths + 3) // 4 * 4
|
||||
|
||||
|
|
@ -455,6 +454,8 @@ class Target():
|
|||
dw = binw.data_writer(self.sdb.byteorder)
|
||||
dw.write_com(binw.Command.RUN_PROG)
|
||||
dw.write_int(0)
|
||||
#for s in self._variables:
|
||||
# add_read_command(dw, self._variables, s)
|
||||
dw.write_com(binw.Command.END_PROG)
|
||||
assert coparun(dw.get_data()) > 0
|
||||
|
||||
|
|
|
|||
|
|
@ -2,24 +2,26 @@ from enum import Enum
|
|||
from typing import Literal
|
||||
import struct
|
||||
|
||||
ByteOrder = Literal['little', 'big']
|
||||
|
||||
Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
||||
('ALLOCATE_CODE', 3), ('COPY_CODE', 4),
|
||||
('PATCH_FUNC', 5), ('PATCH_OBJECT', 6),
|
||||
('RUN_PROG', 64), ('READ_DATA', 65),
|
||||
('END_PROG', 256), ('FREE_MEMORY', 257)])
|
||||
COMMAND_SIZE = 4
|
||||
|
||||
|
||||
class data_writer():
|
||||
def __init__(self, byteorder: Literal['little', 'big']):
|
||||
def __init__(self, byteorder: ByteOrder):
|
||||
self._data: list[tuple[str, bytes, int]] = list()
|
||||
self.byteorder: Literal['little', 'big'] = byteorder
|
||||
self.byteorder: ByteOrder = byteorder
|
||||
|
||||
def write_int(self, value: int, num_bytes: int = 4, signed: bool = False) -> None:
|
||||
self._data.append((f"INT {value}", value.to_bytes(length=num_bytes, byteorder=self.byteorder, signed=signed), 0))
|
||||
|
||||
def write_com(self, value: Enum, num_bytes: int = 4) -> None:
|
||||
self._data.append((value.name, value.value.to_bytes(length=num_bytes, byteorder=self.byteorder, signed=False), 1))
|
||||
def write_com(self, value: Command) -> None:
|
||||
self._data.append((value.name, value.value.to_bytes(length=COMMAND_SIZE, byteorder=self.byteorder, signed=False), 1))
|
||||
|
||||
def write_byte(self, value: int) -> None:
|
||||
self._data.append((f"BYTE {value}", bytes([value]), 0))
|
||||
|
|
@ -52,3 +54,30 @@ class data_writer():
|
|||
def to_file(self, path: str) -> None:
|
||||
with open(path, 'wb') as f:
|
||||
f.write(self.get_data())
|
||||
|
||||
class data_reader():
|
||||
def __init__(self, data: bytes | bytearray, byteorder: ByteOrder):
|
||||
self._data = data
|
||||
self._index: int = 0
|
||||
self.byteorder: ByteOrder = byteorder
|
||||
|
||||
def read_int(self, num_bytes: int = 4, signed: bool = False) -> int:
|
||||
ret = int.from_bytes(self._data[self._index:self._index + num_bytes], byteorder=self.byteorder, signed=signed)
|
||||
self._index += num_bytes
|
||||
return ret
|
||||
|
||||
def read_com(self) -> Command:
|
||||
com_value = int.from_bytes(self._data[self._index:self._index + COMMAND_SIZE], byteorder=self.byteorder)
|
||||
ret = Command(com_value)
|
||||
self._index += COMMAND_SIZE
|
||||
return ret
|
||||
|
||||
def read_byte(self) -> int:
|
||||
ret = self._data[self._index]
|
||||
self._index += 1
|
||||
return ret
|
||||
|
||||
def read_bytes(self, num_bytes: int) -> bytes:
|
||||
ret = self._data[self._index:self._index + num_bytes]
|
||||
self._index += num_bytes
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ def get_function_start() -> str:
|
|||
return """
|
||||
int function_start(){
|
||||
result_int(0); // dummy call instruction before marker gets striped
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
return 1;
|
||||
}
|
||||
"""
|
||||
|
|
@ -19,7 +19,7 @@ def get_function_end() -> str:
|
|||
return """
|
||||
int function_end(){
|
||||
result_int(0);
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
return 1;
|
||||
}
|
||||
"""
|
||||
|
|
@ -28,9 +28,9 @@ def get_function_end() -> str:
|
|||
def get_op_code(op: str, type1: str, type2: str, type_out: str) -> str:
|
||||
return f"""
|
||||
void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
result_{type_out}_{type2}(arg1 {op_signs[op]} arg2, arg2);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
@ -38,9 +38,9 @@ def get_op_code(op: str, type1: str, type2: str, type_out: str) -> str:
|
|||
def get_op_code_float(op: str, type1: str, type2: str) -> str:
|
||||
return f"""
|
||||
void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
result_float_{type2}((float)arg1 {op_signs[op]} arg2, arg2);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
@ -48,9 +48,9 @@ def get_op_code_float(op: str, type1: str, type2: str) -> str:
|
|||
def get_op_code_int(op: str, type1: str, type2: str) -> str:
|
||||
return f"""
|
||||
void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
result_int_{type2}((int)(arg1 {op_signs[op]} arg2), arg2);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
@ -70,9 +70,9 @@ def get_result_stubs2(type1: str, type2: str) -> str:
|
|||
def get_read_reg0_code(type1: str, type2: str, type_out: str) -> str:
|
||||
return f"""
|
||||
void read_{type_out}_reg0_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
result_{type_out}_{type2}(dummy_{type_out}, arg2);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
@ -80,9 +80,9 @@ def get_read_reg0_code(type1: str, type2: str, type_out: str) -> str:
|
|||
def get_read_reg1_code(type1: str, type2: str, type_out: str) -> str:
|
||||
return f"""
|
||||
void read_{type_out}_reg1_{type1}_{type2}({type1} arg1, {type2} arg2) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
result_{type1}_{type_out}(arg1, dummy_{type_out});
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
@ -90,10 +90,10 @@ def get_read_reg1_code(type1: str, type2: str, type_out: str) -> str:
|
|||
def get_write_code(type1: str) -> str:
|
||||
return f"""
|
||||
void write_{type1}({type1} arg1) {{
|
||||
asm volatile (".long 0xF17ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E1");
|
||||
dummy_{type1} = arg1;
|
||||
result_{type1}(arg1);
|
||||
asm volatile (".long 0xF27ECAFE");
|
||||
asm volatile (".long 0x0F1F4400E2");
|
||||
}}
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ from enum import Enum
|
|||
|
||||
ByteOrder = Literal['little', 'big']
|
||||
|
||||
START_MARKER = 0xF17ECAFE
|
||||
END_MARKER = 0xF27ECAFE
|
||||
MARKER_LENGTH = 4
|
||||
START_MARKER = 0x0F1F4400E1 # Nop on x86-64
|
||||
END_MARKER = 0x0F1F4400E2 # Nop on x86-64
|
||||
MARKER_LENGTH = 5
|
||||
|
||||
LENGTH_CALL_INSTRUCTION = 5 # x86_64
|
||||
# on x86_64: call or jmp instruction when tail call optimized
|
||||
LENGTH_CALL_INSTRUCTION = 5
|
||||
|
||||
RelocationType = Enum('RelocationType', [('RELOC_RELATIVE_32', 0)])
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ int main(int argc, char *argv[]) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
parse_commands(file_buff);
|
||||
int ret = parse_commands(file_buff);
|
||||
|
||||
free_memory();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return ret < 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ int parse_commands(uint8_t *bytes) {
|
|||
uint32_t reloc_type;
|
||||
uint32_t offs;
|
||||
uint32_t size;
|
||||
int err_flag = 0;
|
||||
int end_flag = 0;
|
||||
uint32_t rel_entr_point;
|
||||
|
||||
while(!err_flag) {
|
||||
while(!end_flag) {
|
||||
command = *(uint32_t*)bytes;
|
||||
bytes += 4;
|
||||
switch(command) {
|
||||
|
|
@ -61,7 +61,7 @@ int parse_commands(uint8_t *bytes) {
|
|||
data_memory = allocate_data_memory(size);
|
||||
data_memory_len = size;
|
||||
printf("ALLOCATE_DATA size=%i mem_addr=%p\n", size, (void*)data_memory);
|
||||
if (!update_data_offs()) return EXIT_FAILURE;
|
||||
if (!update_data_offs()) end_flag = -4;
|
||||
break;
|
||||
|
||||
case COPY_DATA:
|
||||
|
|
@ -77,7 +77,7 @@ int parse_commands(uint8_t *bytes) {
|
|||
executable_memory_len = size;
|
||||
printf("ALLOCATE_CODE size=%i mem_addr=%p\n", size, (void*)executable_memory);
|
||||
//printf("# d %i c %i off %i\n", data_memory, executable_memory, data_offs);
|
||||
if (!update_data_offs()) return EXIT_FAILURE;
|
||||
if (!update_data_offs()) end_flag = -4;
|
||||
break;
|
||||
|
||||
case COPY_CODE:
|
||||
|
|
@ -126,20 +126,19 @@ int parse_commands(uint8_t *bytes) {
|
|||
break;
|
||||
|
||||
case FREE_MEMORY:
|
||||
size = *(uint32_t*)bytes; bytes += 4;
|
||||
free_memory();
|
||||
break;
|
||||
|
||||
case END_PROG:
|
||||
printf("END_PROG\n");
|
||||
err_flag = 1;
|
||||
end_flag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown command\n");
|
||||
return EXIT_FAILURE;
|
||||
end_flag = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
return end_flag;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,21 @@ def test_ast_generation():
|
|||
|
||||
#r1 = i1 + i3
|
||||
#r2 = i3 * i2
|
||||
|
||||
#c1 = const(4)
|
||||
#i1 = c1 * 2
|
||||
#r1 = i1 + 7
|
||||
#r2 = i1 + 9
|
||||
#out = [Write(r1), Write(r2)]
|
||||
|
||||
c1 = const(4)
|
||||
i1 = c1 * 2
|
||||
r1 = i1 + 7
|
||||
r2 = i1 + 9
|
||||
out = [Write(r1), Write(r2)]
|
||||
c2 = const(2)
|
||||
#i1 = c1 * 2
|
||||
#r1 = i1 + 7 + (c2 + 7 * 9)
|
||||
#r2 = i1 + 9
|
||||
#out = [Write(r1), Write(r2)]
|
||||
r1 = c1 * 5 + 8 + c2 * 3
|
||||
out = [Write(r1)]
|
||||
|
||||
print(out)
|
||||
print('-- get_edges:')
|
||||
|
|
|
|||
|
|
@ -48,10 +48,12 @@ def test_compile():
|
|||
|
||||
c1 = const(4)
|
||||
c2 = const(2)
|
||||
i1 = c1 * 2
|
||||
r1 = i1 + 7 + (c2 + 7 * 9)
|
||||
r2 = i1 + 9
|
||||
out = [Write(r1), Write(r2)]
|
||||
#i1 = c1 * 2
|
||||
#r1 = i1 + 7 + (c2 + 7 * 9)
|
||||
#r2 = i1 + 9
|
||||
#out = [Write(r1), Write(r2)]
|
||||
r1 = c1 * 5 + 8 + c2 * 3
|
||||
out = [Write(r1)]
|
||||
|
||||
il, _ = copapy.compile_to_instruction_list(out, copapy.generic_sdb)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ def test_compile():
|
|||
tg.compile(ret)
|
||||
#time.sleep(5)
|
||||
print('* run and copy ...')
|
||||
#tg.run()
|
||||
tg.run()
|
||||
#print('* finished')
|
||||
|
||||
ret_ref = function(4, 2)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
from copapy.binwrite import data_reader, Command, ByteOrder
|
||||
from copapy.stencil_db import RelocationType
|
||||
|
||||
input_file = "bin/test.copapy"
|
||||
|
||||
output_file = "bin/test_code.bin"
|
||||
|
||||
data_section_offset = 0x2000
|
||||
|
||||
byteorder: ByteOrder = 'little'
|
||||
|
||||
with open(input_file, mode='rb') as f:
|
||||
dr = data_reader(f.read(), byteorder)
|
||||
|
||||
buffer_index: int = 0
|
||||
end_flag: int = 0
|
||||
program_data: bytearray = bytearray([])
|
||||
|
||||
while(end_flag == 0):
|
||||
com = dr.read_com()
|
||||
|
||||
if com == Command.ALLOCATE_DATA:
|
||||
size = dr.read_int()
|
||||
print(f"ALLOCATE_DATA size={size}")
|
||||
elif com == Command.ALLOCATE_CODE:
|
||||
size = dr.read_int()
|
||||
program_data = bytearray(size)
|
||||
print(f"ALLOCATE_CODE size={size}")
|
||||
elif com == Command.COPY_DATA:
|
||||
offs = dr.read_int()
|
||||
size = dr.read_int()
|
||||
datab = dr.read_bytes(size)
|
||||
print(f"COPY_DATA offs={offs} size={size} data={' '.join(hex(d) for d in datab)}")
|
||||
elif com == Command.COPY_CODE:
|
||||
offs = dr.read_int()
|
||||
size = dr.read_int()
|
||||
datab = dr.read_bytes(size)
|
||||
program_data[offs:offs + size] = datab
|
||||
print(f"COPY_CODE offs={offs} size={size} data={' '.join(hex(d) for d in datab[:5])}...")
|
||||
elif com == Command.PATCH_FUNC:
|
||||
offs = dr.read_int()
|
||||
reloc_type = dr.read_int()
|
||||
value = dr.read_int(signed=True)
|
||||
print(f"PATCH_FUNC patch_offs={offs} reloc_type={reloc_type} value={value}")
|
||||
elif com == Command.PATCH_OBJECT:
|
||||
offs = dr.read_int()
|
||||
reloc_type = dr.read_int()
|
||||
value = dr.read_int(signed=True)
|
||||
assert reloc_type == RelocationType.RELOC_RELATIVE_32.value
|
||||
program_data[offs:offs + 4] = (value + data_section_offset).to_bytes(4, byteorder, signed=True)
|
||||
print(f"PATCH_OBJECT patch_offs={offs} reloc_type={reloc_type} value={value}")
|
||||
elif com == Command.RUN_PROG:
|
||||
rel_entr_point = dr.read_int()
|
||||
print(f"RUN_PROG rel_entr_point={rel_entr_point}")
|
||||
elif com == Command.READ_DATA:
|
||||
offs = dr.read_int()
|
||||
size = dr.read_int()
|
||||
print(f"READ_DATA offs={offs} size={size}")
|
||||
elif com == Command.FREE_MEMORY:
|
||||
print("READ_DATA")
|
||||
elif com == Command.END_PROG:
|
||||
print("END_PROG")
|
||||
end_flag = 1
|
||||
else:
|
||||
assert False, f"Unknown command: {com}"
|
||||
|
||||
with open(output_file, mode='wb') as f:
|
||||
f.write(program_data)
|
||||
|
||||
print('OK')
|
||||
Loading…
Reference in New Issue