mirror of https://github.com/Nonannet/copapy.git
Compare commits
7 Commits
afc442ada6
...
7f963d7e43
| Author | SHA1 | Date |
|---|---|---|
|
|
7f963d7e43 | |
|
|
dd7fb12c64 | |
|
|
d2069d5d07 | |
|
|
accb03f042 | |
|
|
2eb49cc2e5 | |
|
|
c7c8db6332 | |
|
|
8fcf0dedac |
|
|
@ -214,6 +214,10 @@ jobs:
|
|||
gcc -O3 -static -DENABLE_LOGGING -o build/runner/coparun src/coparun/runmem.c \
|
||||
src/coparun/coparun.c src/coparun/mem_man.c && \
|
||||
pytest && \
|
||||
export CP_TARGET_ARCH=armv7thumb && \
|
||||
pytest && \
|
||||
export CP_TARGET_ARCH=armv7mthumb && \
|
||||
pytest && \
|
||||
bash tools/create_asm.sh"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2),
|
|||
('PATCH_OBJECT_ABS', 0x2002),
|
||||
('PATCH_OBJECT_REL', 0x2003),
|
||||
('PATCH_OBJECT_ARM32_ABS', 0x2004),
|
||||
('PATCH_OBJECT_ARM32_ABS_THM', 0x2006),
|
||||
('ENTRY_POINT', 7),
|
||||
('RUN_PROG', 64), ('READ_DATA', 65),
|
||||
('END_COM', 256), ('FREE_MEMORY', 257), ('DUMP_CODE', 258)])
|
||||
|
|
|
|||
|
|
@ -393,14 +393,14 @@ def compile_to_dag(node_list: Iterable[Node], sdb: stencil_database) -> tuple[bi
|
|||
# assemble stencils to main program and patch stencils
|
||||
data = sdb.get_function_code('entry_function_shell', 'start')
|
||||
data_list.append(data)
|
||||
print(f"* entry_function_shell (0) " + ' '.join(f'{d:02X}' for d in data))
|
||||
#print(f"* entry_function_shell (0) " + ' '.join(f'{d:02X}' for d in data))
|
||||
offset = aux_func_len + len(data)
|
||||
|
||||
for associated_net, node in extended_output_ops:
|
||||
assert node.name in sdb.stencil_definitions, f"- Warning: {node.name} stencil not found"
|
||||
data = sdb.get_stencil_code(node.name)
|
||||
data_list.append(data)
|
||||
print(f"* {node.name} ({offset}) " + ' '.join(f'{d:02X}' for d in data))
|
||||
#print(f"* {node.name} ({offset}) " + ' '.join(f'{d:02X}' for d in data))
|
||||
|
||||
for reloc in sdb.get_relocations(node.name, stencil=True):
|
||||
if reloc.target_symbol_info in ('STT_OBJECT', 'STT_NOTYPE', 'STT_SECTION'):
|
||||
|
|
@ -453,7 +453,7 @@ def compile_to_dag(node_list: Iterable[Node], sdb: stencil_database) -> tuple[bi
|
|||
for reloc in sdb.get_relocations(name):
|
||||
|
||||
if not reloc.target_section_index:
|
||||
assert reloc.pelfy_reloc.type == 'R_ARM_V4BX', (reloc.pelfy_reloc.type, name)
|
||||
assert reloc.pelfy_reloc.type == 'R_ARM_V4BX', (reloc.pelfy_reloc.type, name, reloc.pelfy_reloc.symbol.name)
|
||||
|
||||
elif reloc.target_symbol_info in {'STT_OBJECT', 'STT_NOTYPE', 'STT_SECTION'}:
|
||||
# Patch constants/variable addresses on heap
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ def get_42(x: value[Any]) -> value[float]: ...
|
|||
def get_42(x: NumLike) -> value[float] | float:
|
||||
"""Returns the value representing the constant 42"""
|
||||
if isinstance(x, value):
|
||||
return add_op('get_42', [x, x])
|
||||
return add_op('get_42', [x])
|
||||
return float((int(x) * 3.0 + 42.0) * 5.0 + 21.0)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from dataclasses import dataclass
|
|||
from typing import Generator, Literal, Iterable, TYPE_CHECKING
|
||||
import struct
|
||||
import platform
|
||||
import os
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pelfy
|
||||
|
|
@ -46,6 +47,10 @@ class patch_entry:
|
|||
|
||||
|
||||
def detect_process_arch() -> str:
|
||||
cp_target_arch = os.environ.get("CP_TARGET_ARCH")
|
||||
if cp_target_arch:
|
||||
return cp_target_arch
|
||||
|
||||
bits = struct.calcsize("P") * 8
|
||||
arch = platform.machine().lower()
|
||||
|
||||
|
|
@ -305,21 +310,20 @@ class stencil_database():
|
|||
scale = 8
|
||||
#print(f" *> {patch_value=} {symbol_address=} {pr.fields['r_addend']=}, {function_offset=}")
|
||||
|
||||
elif pr.type.endswith('_MOVW_ABS_NC'):
|
||||
# R_ARM_MOVW_ABS_NC
|
||||
elif pr.type == 'R_ARM_MOVW_ABS_NC':
|
||||
# (S + A) & 0xFFFF
|
||||
mask = 0xFFFF
|
||||
patch_value = symbol_address + pr.fields['r_addend']
|
||||
symbol_type = symbol_type + 0x04 # Absolut value
|
||||
#print(f" *> {pr.type} {patch_value=} {symbol_address=}, {function_offset=}")
|
||||
|
||||
elif pr.type.endswith('_MOVT_ABS'):
|
||||
# R_ARM_MOVT_ABS
|
||||
elif pr.type =='R_ARM_MOVT_ABS':
|
||||
# (S + A) & 0xFFFF0000
|
||||
mask = 0xFFFF0000
|
||||
patch_value = symbol_address + pr.fields['r_addend']
|
||||
symbol_type = symbol_type + 0x04 # Absolut value
|
||||
scale = 0x10000
|
||||
#print(f" *> {pr.type} {patch_value=} {symbol_address=}, {function_offset=}, {pr.fields['r_addend']=}")
|
||||
|
||||
elif pr.type.endswith('_ABS32'):
|
||||
# R_ARM_ABS32
|
||||
|
|
@ -330,9 +334,24 @@ class stencil_database():
|
|||
elif pr.type.endswith('_THM_JUMP24') or pr.type.endswith('_THM_CALL'):
|
||||
# R_ARM_THM_JUMP24
|
||||
# S + A - P
|
||||
#assert pr.fields['r_addend'] == 0, pr.fields['r_addend']
|
||||
patch_value = symbol_address - (patch_offset + 4) #+ pr.fields['r_addend']
|
||||
patch_value = symbol_address - patch_offset + pr.fields['r_addend']
|
||||
symbol_type = symbol_type + 0x05 # PATCH_FUNC_ARM32_THM
|
||||
#print(f" *> {pr.type} {patch_value=} {symbol_address=} {pr.fields['r_addend']=} {pr.bits=}, {function_offset=} {patch_offset=}")
|
||||
|
||||
elif pr.type == 'R_ARM_THM_MOVW_ABS_NC':
|
||||
# (S + A) & 0xFFFF
|
||||
mask = 0xFFFF
|
||||
patch_value = symbol_address + pr.fields['r_addend']
|
||||
symbol_type = symbol_type + 0x06 # PATCH_OBJECT_ARM32_ABS_THM
|
||||
#print(f" *> {pr.type} {patch_value=} {symbol_address=}, {function_offset=}, {pr.fields['r_addend']=}")
|
||||
|
||||
elif pr.type == 'R_ARM_THM_MOVT_ABS':
|
||||
# (S + A) & 0xFFFF0000
|
||||
mask = 0xFFFF0000
|
||||
patch_value = symbol_address + pr.fields['r_addend']
|
||||
symbol_type = symbol_type + 0x06 # PATCH_OBJECT_ARM32_ABS_THM
|
||||
scale = 0x10000
|
||||
#print(f" *> {pr.type} {patch_value=} {symbol_address=}, {function_offset=}, {pr.fields['r_addend']=}")
|
||||
|
||||
else:
|
||||
raise NotImplementedError(f"Relocation type {pr.type} in {relocation.pelfy_reloc.target_section.name} pointing to {relocation.pelfy_reloc.symbol.name} not implemented")
|
||||
|
|
|
|||
|
|
@ -50,6 +50,32 @@ void patch_arm32_abs(uint8_t *patch_addr, uint32_t imm16)
|
|||
*((uint32_t *)patch_addr) = instr;
|
||||
}
|
||||
|
||||
void patch_arm_thm_abs(uint8_t *patch_addr, uint32_t imm16)
|
||||
{
|
||||
// Thumb MOVW (T3) / MOVT (T1) encoding
|
||||
|
||||
uint16_t *instr16 = (uint16_t *)patch_addr;
|
||||
uint16_t first_half = instr16[0];
|
||||
uint16_t second_half = instr16[1];
|
||||
|
||||
// Extract fields from imm16
|
||||
uint32_t imm4 = (imm16 >> 12) & 0xF;
|
||||
uint32_t i = (imm16 >> 11) & 0x1;
|
||||
uint32_t imm3 = (imm16 >> 8) & 0x7;
|
||||
uint32_t imm8 = imm16 & 0xFF;
|
||||
|
||||
// Clear bits
|
||||
first_half &= (uint16_t)(~(0x000F | (1 << 10)));
|
||||
second_half &= (uint16_t)(~(0x00FF | (0x7 << 12)));
|
||||
|
||||
// Set new fields
|
||||
first_half |= (uint16_t)((imm4 << 0) | (i << 10));
|
||||
second_half |= (uint16_t)(imm8 | (imm3 << 12));
|
||||
|
||||
instr16[0] = first_half;
|
||||
instr16[1] = second_half;
|
||||
}
|
||||
|
||||
void patch_arm_thm_jump24(uint8_t *patch_addr, int32_t imm24)
|
||||
{
|
||||
// Read the 32-bit instruction (two halfwords)
|
||||
|
|
@ -77,8 +103,8 @@ void patch_arm_thm_jump24(uint8_t *patch_addr, int32_t imm24)
|
|||
second_half &= 0xD000; // Keep upper 5 bits
|
||||
|
||||
// Set new imm fields
|
||||
first_half |= (S << 10) | imm10;
|
||||
second_half |= (J1 << 13) | (J2 << 11) | imm11;
|
||||
first_half |= (uint16_t)((S << 10) | imm10);
|
||||
second_half |= (uint16_t)((J1 << 13) | (J2 << 11) | imm11);
|
||||
|
||||
// Write back
|
||||
instr16[0] = first_half;
|
||||
|
|
@ -225,6 +251,16 @@ int parse_commands(runmem_t *context, uint8_t *bytes) {
|
|||
patch_arm_thm_jump24(context->executable_memory + offs, value);
|
||||
break;
|
||||
|
||||
case PATCH_OBJECT_ARM32_ABS_THM:
|
||||
offs = *(uint32_t*)bytes; bytes += 4;
|
||||
patch_mask = *(uint32_t*)bytes; bytes += 4;
|
||||
patch_scale = *(int32_t*)bytes; bytes += 4;
|
||||
value = *(int32_t*)bytes; bytes += 4;
|
||||
LOG("PATCH_OBJECT_ARM32_ABS_THM patch_offs=%i patch_mask=%#08x scale=%i value=%i imm16=%#04x\n",
|
||||
offs, patch_mask, patch_scale, value, (uint32_t)((uintptr_t)(context->data_memory + value) & patch_mask) / (uint32_t)patch_scale);
|
||||
patch_arm_thm_abs(context->executable_memory + offs, (uint32_t)((uintptr_t)(context->data_memory + value) & patch_mask) / (uint32_t)patch_scale);
|
||||
break;
|
||||
|
||||
case ENTRY_POINT:
|
||||
rel_entr_point = *(uint32_t*)bytes; bytes += 4;
|
||||
context->entr_point = (entry_point_t)(context->executable_memory + rel_entr_point);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#define PATCH_OBJECT_ABS 0x2002
|
||||
#define PATCH_OBJECT_REL 0x2003
|
||||
#define PATCH_OBJECT_ARM32_ABS 0x2004
|
||||
#define PATCH_OBJECT_ARM32_ABS_THM 0x2006
|
||||
#define ENTRY_POINT 7
|
||||
#define RUN_PROG 64
|
||||
#define READ_DATA 65
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ def function1(c1: NumLike) -> list[NumLike]:
|
|||
c1 + 4, c1 - 4,
|
||||
c1 > 2, c1 > 100, c1 < 4, c1 < 100]
|
||||
|
||||
def function1ex(c1: NumLike) -> list[NumLike]:
|
||||
return [c1 // 4]
|
||||
|
||||
|
||||
def function2(c1: NumLike) -> list[NumLike]:
|
||||
return [c1 * 4.44, c1 * -4.44]
|
||||
|
|
@ -90,24 +93,21 @@ def test_compile():
|
|||
c_f = value(1.111)
|
||||
c_b = value(True)
|
||||
|
||||
#ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [value(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
||||
#ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
||||
|
||||
ret_test = (c_i * 100 + 5,)
|
||||
ret_ref = (9 * 100 + 5,)
|
||||
ret_test = function1(c_i) + function1(c_f) + function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [value(9) % 2] + iiftests(c_i) + iiftests(c_f) + [cp.asin(c_i/10)]
|
||||
ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] + iiftests(9) + iiftests(1.111) + [cp.asin(9/10)]
|
||||
|
||||
out = [Store(r) for r in ret_test]
|
||||
|
||||
sdb = backend.stencil_db_from_package('armv7thumb')
|
||||
sdb = backend.stencil_db_from_package('armv7mthumb')
|
||||
dw, variables = compile_to_dag(out, sdb)
|
||||
|
||||
#dw.write_com(_binwrite.Command.READ_DATA)
|
||||
#dw.write_int(0)
|
||||
#dw.write_int(28)
|
||||
|
||||
# run program command
|
||||
#dw.write_com(_binwrite.Command.RUN_PROG)
|
||||
dw.write_com(_binwrite.Command.DUMP_CODE)
|
||||
du = dw.copy()
|
||||
dw.write_com(_binwrite.Command.RUN_PROG)
|
||||
du.write_com(_binwrite.Command.DUMP_CODE)
|
||||
|
||||
for v in ret_test:
|
||||
assert isinstance(v, value)
|
||||
|
|
@ -118,11 +118,13 @@ def test_compile():
|
|||
#dw.write_int(28)
|
||||
|
||||
dw.write_com(_binwrite.Command.END_COM)
|
||||
du.write_com(_binwrite.Command.END_COM)
|
||||
|
||||
#print('* Data to runner:')
|
||||
#dw.print()
|
||||
|
||||
dw.to_file('build/runner/test-armv7thumb.copapy')
|
||||
du.to_file('build/runner/test-armv7thumb-dump.copapy')
|
||||
|
||||
if not check_for_qemu():
|
||||
warnings.warn("qemu-armv7 not found, armv7 test skipped!", UserWarning)
|
||||
|
|
@ -131,12 +133,14 @@ def test_compile():
|
|||
warnings.warn("armv7thumb runner not found, armv7thumb test skipped!", UserWarning)
|
||||
return
|
||||
|
||||
command = qemu_command + ['build/runner/coparun-armv7thumb', 'build/runner/test-armv7thumb.copapy'] + ['build/runner/test.copapy-armv7thumb.bin']
|
||||
#try:
|
||||
print('----- Dump code...')
|
||||
command = qemu_command + ['build/runner/coparun-armv7thumb', 'build/runner/test-armv7thumb-dump.copapy', 'build/runner/test.copapy-armv7thumb.bin']
|
||||
result = run_command(command)
|
||||
#except FileNotFoundError:
|
||||
# warnings.warn(f"Test skipped, executable not found.", UserWarning)
|
||||
# return
|
||||
|
||||
print('----- Run code...')
|
||||
command = qemu_command + ['build/runner/coparun-armv7thumb', 'build/runner/test-armv7thumb.copapy']
|
||||
result = run_command(command)
|
||||
|
||||
|
||||
print('* Output from runner:\n--')
|
||||
print(result)
|
||||
|
|
@ -167,5 +171,14 @@ def test_compile():
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
#test_example()
|
||||
test_slow_31bit_int_list_hash()
|
||||
test_compile()
|
||||
|
||||
|
||||
"""
|
||||
qemu-arm -d in_asm,exec,cpu_reset -D qemu.log build/runner/coparun-armv7thumb build/runner/test-armv7thumb.copapy build/runner/test.copapy-armv7thumb.bin
|
||||
|
||||
qemu-arm -d in_asm,exec -D qemu_trace.log \
|
||||
-global driver=pl011.audiomaddr,property=addr,value=0xff7ec000 \
|
||||
-global driver=pl011.audiomaddr,property=size,value=0x100000 \
|
||||
your_binary
|
||||
"""
|
||||
|
|
@ -4,10 +4,10 @@ set -eu
|
|||
ARCH=${1:-x86_64}
|
||||
|
||||
case "$ARCH" in
|
||||
(x86_64|arm-v6|arm-v7|arm-v7-thumb|arm-v7m-thumb|all)
|
||||
(x86_64|arm64|arm-v6|arm-v7|arm-v7-thumb|arm-v7m-thumb|all)
|
||||
;;
|
||||
(*)
|
||||
echo "Usage: $0 [x86_64|arm-v6|arm-v7|arm-v6-thumb|arm-v7m-thumb|all]"
|
||||
echo "Usage: $0 [x86_64|arm64|arm-v6|arm-v7|arm-v6-thumb|arm-v7m-thumb|all]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
@ -42,13 +42,44 @@ if [[ "$ARCH" == "x86_64" || "$ARCH" == "all" ]]; then
|
|||
-o build/runner/coparun
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# ARM 64
|
||||
#######################################
|
||||
if [[ "$ARCH" == "arm64" || "$ARCH" == "all" ]]; then
|
||||
echo "--------------arm64----------------"
|
||||
|
||||
LIBGCC=$(aarch64-linux-gnu-gcc -print-libgcc-file-name)
|
||||
|
||||
aarch64-linux-gnu-gcc -fno-pic -ffunction-sections \
|
||||
-c $SRC -O3 -o build/stencils/stencils.o
|
||||
|
||||
aarch64-linux-gnu-ld -r \
|
||||
build/stencils/stencils.o \
|
||||
build/musl/musl_objects_arm64.o \
|
||||
$LIBGCC \
|
||||
-o $DEST/stencils_arm64_O3.o
|
||||
|
||||
aarch64-linux-gnu-objdump -d -x \
|
||||
$DEST/stencils_arm64_O3.o \
|
||||
> build/stencils/stencils_arm64_O3.asm
|
||||
|
||||
aarch64-linux-gnu-gcc \
|
||||
-Wall -Wextra -Wconversion -Wsign-conversion -static \
|
||||
-Wshadow -Wstrict-overflow -O3 \
|
||||
-DENABLE_LOGGING \
|
||||
src/coparun/runmem.c \
|
||||
src/coparun/coparun.c \
|
||||
src/coparun/mem_man.c \
|
||||
-o build/runner/coparun-arm64
|
||||
fi
|
||||
|
||||
#######################################
|
||||
# ARM v6
|
||||
#######################################
|
||||
if [[ "$ARCH" == "arm-v6" || "$ARCH" == "all" ]]; then
|
||||
echo "--------------arm-v6 32 bit----------------"
|
||||
|
||||
LIBGCC=$(arm-none-eabi-gcc -print-libgcc-file-name)
|
||||
LIBGCC=$(arm-none-eabi-gcc -march=armv6 -mfpu=vfp -mfloat-abi=hard -marm -print-libgcc-file-name)
|
||||
|
||||
arm-none-eabi-gcc -fno-pic -ffunction-sections \
|
||||
-march=armv6 -mfpu=vfp -mfloat-abi=hard -marm \
|
||||
|
|
@ -81,7 +112,7 @@ fi
|
|||
if [[ "$ARCH" == "arm-v7" || "$ARCH" == "all" ]]; then
|
||||
echo "--------------arm-v7 32 bit----------------"
|
||||
|
||||
LIBGCC=$(arm-none-eabi-gcc -print-libgcc-file-name)
|
||||
LIBGCC=$(arm-none-eabi-gcc -march=armv7-a -mfpu=neon-vfpv3 -mfloat-abi=hard -marm -print-libgcc-file-name)
|
||||
|
||||
arm-none-eabi-gcc -fno-pic -ffunction-sections \
|
||||
-march=armv7-a -mfpu=neon-vfpv3 -mfloat-abi=hard -marm \
|
||||
|
|
@ -114,7 +145,7 @@ fi
|
|||
if [[ "$ARCH" == "arm-v7-thumb" || "$ARCH" == "all" ]]; then
|
||||
echo "--------------arm-v7a-thumb 32 bit----------------"
|
||||
|
||||
LIBGCC=$(arm-none-eabi-gcc -print-libgcc-file-name)
|
||||
LIBGCC=$(arm-none-eabi-gcc -march=armv7 -mfpu=vfp3 -mthumb -print-libgcc-file-name)
|
||||
|
||||
arm-none-eabi-gcc -fno-pic -ffunction-sections \
|
||||
-march=armv7-a -mfpu=neon-vfpv3 -mfloat-abi=hard -mthumb \
|
||||
|
|
@ -122,7 +153,7 @@ if [[ "$ARCH" == "arm-v7-thumb" || "$ARCH" == "all" ]]; then
|
|||
|
||||
arm-none-eabi-ld -r \
|
||||
build/stencils/stencils.o \
|
||||
build/musl/musl_objects_armv7.o \
|
||||
build/musl/musl_objects_armv7thumb.o \
|
||||
$LIBGCC \
|
||||
-o $DEST/stencils_armv7thumb_O3.o
|
||||
|
||||
|
|
@ -147,7 +178,7 @@ fi
|
|||
if [[ "$ARCH" == "arm-v7m-thumb" || "$ARCH" == "all" ]]; then
|
||||
echo "--------------arm-v7m-thumb 32 bit----------------"
|
||||
|
||||
LIBGCC=$(arm-none-eabi-gcc -print-libgcc-file-name)
|
||||
LIBGCC=$(arm-none-eabi-gcc -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -print-libgcc-file-name)
|
||||
|
||||
arm-none-eabi-gcc -fno-pic -ffunction-sections \
|
||||
-march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
bash tools/build.sh arm-v7-thumb
|
||||
python tests/test_ops_armv7thumb.py
|
||||
qemu-arm -d in_asm -D qemu.log build/runner/coparun-armv7thumb build/runner/test-armv7thumb.copapy build/runner/test.copapy-armv7thumb.bin
|
||||
arm-none-eabi-objdump -D -b binary -marm -M force-thumb --adjust-vma=0xff7ed000 build/runner/test.copapy-armv7thumb.bin > build/runner/test.copapy-armv7thumb.asm
|
||||
Loading…
Reference in New Issue