Skip to content

Commit b8f9ac5

Browse files
committed
py: Implement ptr32 load and store in viper emitter.
1 parent 21f43ba commit b8f9ac5

8 files changed

Lines changed: 156 additions & 3 deletions

File tree

py/asmx64.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,16 @@ void asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest
340340
asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);
341341
}
342342

343+
void asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {
344+
assert(dest_r64 < 8);
345+
if (src_r64 < 8) {
346+
asm_x64_write_byte_1(as, OPCODE_MOV_R64_TO_RM64);
347+
} else {
348+
asm_x64_write_byte_2(as, REX_PREFIX | REX_R, OPCODE_MOV_R64_TO_RM64);
349+
}
350+
asm_x64_write_r64_disp(as, src_r64, dest_r64, dest_disp);
351+
}
352+
343353
void asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp) {
344354
// use REX prefix for 64 bit operation
345355
asm_x64_write_byte_2(as, REX_PREFIX | REX_W | (src_r64 < 8 ? 0 : REX_R) | (dest_r64 < 8 ? 0 : REX_B), OPCODE_MOV_R64_TO_RM64);
@@ -366,6 +376,16 @@ void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int de
366376
asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);
367377
}
368378

379+
void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {
380+
assert(src_r64 < 8);
381+
if (dest_r64 < 8) {
382+
asm_x64_write_byte_1(as, OPCODE_MOV_RM64_TO_R64);
383+
} else {
384+
asm_x64_write_byte_2(as, REX_PREFIX | REX_R, OPCODE_MOV_RM64_TO_R64);
385+
}
386+
asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp);
387+
}
388+
369389
void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) {
370390
// use REX prefix for 64 bit operation
371391
asm_x64_write_byte_2(as, REX_PREFIX | REX_W | (dest_r64 < 8 ? 0 : REX_R) | (src_r64 < 8 ? 0 : REX_B), OPCODE_MOV_RM64_TO_R64);

py/asmx64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r
9494
void asm_x64_mov_i64_to_r64_aligned(asm_x64_t *as, int64_t src_i64, int dest_r64);
9595
void asm_x64_mov_r8_to_mem8(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
9696
void asm_x64_mov_r16_to_mem16(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
97+
void asm_x64_mov_r32_to_mem32(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
9798
void asm_x64_mov_r64_to_mem64(asm_x64_t *as, int src_r64, int dest_r64, int dest_disp);
9899
void asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
99100
void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
101+
void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
100102
void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
101103
void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
102104
void asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);

py/emitnative.c

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,13 @@
152152
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (word_offset), (reg_dest))
153153
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest))
154154
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest))
155+
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 0, (reg_dest))
155156

156157
#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0)
157158
#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (word_offset))
158159
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)
159160
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)
161+
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)
160162

161163
#elif N_X86
162164

@@ -295,11 +297,13 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
295297
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (word_offset), (reg_dest))
296298
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest))
297299
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest))
300+
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest))
298301

299302
#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)
300303
#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (word_offset))
301304
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)
302305
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)
306+
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)
303307

304308
#elif N_THUMB
305309

@@ -388,11 +392,13 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
388392
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), (word_offset))
389393
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
390394
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
395+
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
391396

392397
#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
393398
#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), (word_offset))
394399
#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
395400
#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
401+
#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
396402

397403
#elif N_ARM
398404

@@ -480,11 +486,13 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
480486
#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset))
481487
#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base))
482488
#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base))
489+
#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base))
483490

484491
#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0)
485492
#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_str_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset))
486493
#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base))
487494
#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base))
495+
#define ASM_STORE32_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base))
488496

489497
#else
490498

@@ -513,10 +521,11 @@ typedef enum {
513521
VTYPE_PTR = 0x10 | MP_NATIVE_TYPE_UINT, // pointer to word sized entity
514522
VTYPE_PTR8 = 0x20 | MP_NATIVE_TYPE_UINT,
515523
VTYPE_PTR16 = 0x30 | MP_NATIVE_TYPE_UINT,
516-
VTYPE_PTR_NONE = 0x40 | MP_NATIVE_TYPE_UINT,
524+
VTYPE_PTR32 = 0x40 | MP_NATIVE_TYPE_UINT,
525+
VTYPE_PTR_NONE = 0x50 | MP_NATIVE_TYPE_UINT,
517526

518-
VTYPE_UNBOUND = 0x50 | MP_NATIVE_TYPE_OBJ,
519-
VTYPE_BUILTIN_CAST = 0x60 | MP_NATIVE_TYPE_OBJ,
527+
VTYPE_UNBOUND = 0x60 | MP_NATIVE_TYPE_OBJ,
528+
VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ,
520529
} vtype_kind_t;
521530

522531
STATIC qstr vtype_to_qstr(vtype_kind_t vtype) {
@@ -528,6 +537,7 @@ STATIC qstr vtype_to_qstr(vtype_kind_t vtype) {
528537
case VTYPE_PTR: return MP_QSTR_ptr;
529538
case VTYPE_PTR8: return MP_QSTR_ptr8;
530539
case VTYPE_PTR16: return MP_QSTR_ptr16;
540+
case VTYPE_PTR32: return MP_QSTR_ptr32;
531541
case VTYPE_PTR_NONE: default: return MP_QSTR_None;
532542
}
533543
}
@@ -600,6 +610,7 @@ STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t ar
600610
case MP_QSTR_ptr: type = VTYPE_PTR; break;
601611
case MP_QSTR_ptr8: type = VTYPE_PTR8; break;
602612
case MP_QSTR_ptr16: type = VTYPE_PTR16; break;
613+
case MP_QSTR_ptr32: type = VTYPE_PTR32; break;
603614
default: EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "unknown type '%q'", arg2); return;
604615
}
605616
if (op == MP_EMIT_NATIVE_TYPE_RETURN) {
@@ -1391,6 +1402,8 @@ STATIC void emit_native_load_global(emit_t *emit, qstr qst) {
13911402
emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR8);
13921403
} else if (emit->do_viper_types && qst == MP_QSTR_ptr16) {
13931404
emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR16);
1405+
} else if (emit->do_viper_types && qst == MP_QSTR_ptr32) {
1406+
emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR32);
13941407
} else {
13951408
emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qst, REG_ARG_1);
13961409
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
@@ -1494,6 +1507,23 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
14941507
ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index)
14951508
break;
14961509
}
1510+
case VTYPE_PTR32: {
1511+
// pointer to 32-bit memory
1512+
if (index_value != 0) {
1513+
// index is a non-zero immediate
1514+
#if N_THUMB
1515+
if (index_value > 0 && index_value < 32) {
1516+
asm_thumb_ldr_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);
1517+
break;
1518+
}
1519+
#endif
1520+
ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);
1521+
ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base
1522+
reg_base = reg_index;
1523+
}
1524+
ASM_LOAD32_REG_REG(emit->as, REG_RET, reg_base); // load from (base+4*index)
1525+
break;
1526+
}
14971527
default:
14981528
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
14991529
"can't load from '%q'", vtype_to_qstr(vtype_base));
@@ -1521,6 +1551,16 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
15211551
ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index)
15221552
break;
15231553
}
1554+
case VTYPE_PTR32: {
1555+
// pointer to word-size memory
1556+
assert(vtype_index == VTYPE_INT);
1557+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1558+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1559+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1560+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1561+
ASM_LOAD32_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+4*index)
1562+
break;
1563+
}
15241564
default:
15251565
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
15261566
"can't load from '%q'", vtype_to_qstr(vtype_base));
@@ -1690,6 +1730,27 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
16901730
ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index)
16911731
break;
16921732
}
1733+
case VTYPE_PTR32: {
1734+
// pointer to 32-bit memory
1735+
if (index_value != 0) {
1736+
// index is a non-zero immediate
1737+
#if N_THUMB
1738+
if (index_value > 0 && index_value < 32) {
1739+
asm_thumb_str_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);
1740+
break;
1741+
}
1742+
#endif
1743+
ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index);
1744+
#if N_ARM
1745+
asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
1746+
return;
1747+
#endif
1748+
ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base
1749+
reg_base = reg_index;
1750+
}
1751+
ASM_STORE32_REG_REG(emit->as, reg_value, reg_base); // store value to (base+4*index)
1752+
break;
1753+
}
16931754
default:
16941755
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
16951756
"can't store to '%q'", vtype_to_qstr(vtype_base));
@@ -1732,6 +1793,20 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
17321793
ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index)
17331794
break;
17341795
}
1796+
case VTYPE_PTR32: {
1797+
// pointer to 32-bit memory
1798+
assert(vtype_index == VTYPE_INT);
1799+
#if N_ARM
1800+
asm_arm_str_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);
1801+
break;
1802+
#endif
1803+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1804+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1805+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1806+
ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1807+
ASM_STORE32_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+4*index)
1808+
break;
1809+
}
17351810
default:
17361811
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
17371812
"can't store to '%q'", vtype_to_qstr(vtype_base));
@@ -2311,6 +2386,7 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u
23112386
case VTYPE_PTR:
23122387
case VTYPE_PTR8:
23132388
case VTYPE_PTR16:
2389+
case VTYPE_PTR32:
23142390
case VTYPE_PTR_NONE:
23152391
emit_fold_stack_top(emit, REG_ARG_1);
23162392
emit_post_top_set_vtype(emit, vtype_cast);

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Q(uint)
103103
Q(ptr)
104104
Q(ptr8)
105105
Q(ptr16)
106+
Q(ptr32)
106107
#endif
107108

108109
#if MICROPY_EMIT_INLINE_THUMB
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# test loading from ptr32 type
2+
3+
@micropython.viper
4+
def get(src:ptr32) -> int:
5+
return src[0]
6+
7+
@micropython.viper
8+
def get1(src:ptr32) -> int:
9+
return src[1]
10+
11+
@micropython.viper
12+
def memadd(src:ptr32, n:int) -> int:
13+
sum = 0
14+
for i in range(n):
15+
sum += src[i]
16+
return sum
17+
18+
b = bytearray(b'\x12\x12\x12\x12\x34\x34\x34\x34')
19+
print(b)
20+
print(hex(get(b)), hex(get1(b)))
21+
print(hex(memadd(b, 2)))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bytearray(b'\x12\x12\x12\x124444')
2+
0x12121212 0x34343434
3+
0x46464646
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# test store to ptr32 type
2+
3+
@micropython.viper
4+
def set(dest:ptr32, val:int):
5+
dest[0] = val
6+
7+
@micropython.viper
8+
def set1(dest:ptr32, val:int):
9+
dest[1] = val
10+
11+
@micropython.viper
12+
def memset(dest:ptr32, val:int, n:int):
13+
for i in range(n):
14+
dest[i] = val
15+
16+
b = bytearray(8)
17+
print(b)
18+
19+
set(b, 0x42424242)
20+
print(b)
21+
22+
set1(b, 0x43434343)
23+
print(b)
24+
25+
memset(b, 0x44444444, len(b) // 4)
26+
print(b)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
2+
bytearray(b'BBBB\x00\x00\x00\x00')
3+
bytearray(b'BBBBCCCC')
4+
bytearray(b'DDDDDDDD')

0 commit comments

Comments
 (0)