Skip to content

Commit 86ddfc5

Browse files
authored
Merge pull request #126 from DrXiao/master
Generate a sequence of instructions for divisions on Arm targets
2 parents 4530829 + 9700844 commit 86ddfc5

File tree

7 files changed

+329
-9
lines changed

7 files changed

+329
-9
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,12 @@ Run `make` and you should see this:
9191

9292
File `out/shecc` is the first stage compiler. Its usage:
9393
```
94-
shecc [-o output] [--no-libc] [--dump-ir] <infile.c>
94+
shecc [-o output] [+m] [--no-libc] [--dump-ir] <infile.c>
9595
```
9696

9797
Compiler options:
9898
- `-o` : output file name (default: out.elf)
99+
- `+m` : Enable hardware multiplication and division instructions (default: disabled)
99100
- `--no-libc` : Exclude embedded C library (default: embedded)
100101
- `--dump-ir` : Dump intermediate representation (IR)
101102

src/arm-codegen.c

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
7474
case OP_add:
7575
case OP_sub:
7676
case OP_mul:
77-
case OP_div:
7877
case OP_lshift:
7978
case OP_rshift:
8079
case OP_bit_and:
@@ -85,11 +84,24 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
8584
case OP_bit_not:
8685
elf_offset += 4;
8786
return;
87+
case OP_div:
88+
if (hard_mul_div) {
89+
elf_offset += 4;
90+
} else {
91+
elf_offset += 104;
92+
}
93+
return;
94+
case OP_mod:
95+
if (hard_mul_div) {
96+
elf_offset += 12;
97+
} else {
98+
elf_offset += 104;
99+
}
100+
return;
88101
case OP_load_data_address:
89102
elf_offset += 8;
90103
return;
91104
case OP_address_of_func:
92-
case OP_mod:
93105
case OP_eq:
94106
case OP_neq:
95107
case OP_gt:
@@ -323,12 +335,76 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
323335
emit(__mul(__AL, rd, rn, rm));
324336
return;
325337
case OP_div:
326-
emit(__div(__AL, rd, rm, rn));
338+
if (hard_mul_div) {
339+
emit(__div(__AL, rd, rm, rn));
340+
} else {
341+
/* Obtain absoulte values of dividend and divisor */
342+
emit(__srl_amt(__AL, 0, arith_rs, __r8, rn, 31));
343+
emit(__add_r(__AL, rn, rn, __r8));
344+
emit(__eor_r(__AL, rn, rn, __r8));
345+
emit(__srl_amt(__AL, 0, arith_rs, __r9, rm, 31));
346+
emit(__add_r(__AL, rm, rm, __r9));
347+
emit(__eor_r(__AL, rm, rm, __r9));
348+
emit(__eor_r(__AL, __r10, __r8, __r9));
349+
/* Unsigned integer division */
350+
emit(__zero(__r9));
351+
emit(__mov_i(__AL, __r8, 1));
352+
emit(__cmp_i(__AL, rm, 0));
353+
emit(__b(__EQ, 52));
354+
emit(__cmp_i(__AL, rn, 0));
355+
emit(__b(__EQ, 44));
356+
emit(__cmp_r(__AL, rm, rn));
357+
emit(__sll_amt(__CC, 0, logic_ls, rm, rm, 1));
358+
emit(__sll_amt(__CC, 0, logic_ls, __r8, __r8, 1));
359+
emit(__b(__CC, -12));
360+
emit(__cmp_r(__AL, rn, rm));
361+
emit(__sub_r(__CS, rn, rn, rm));
362+
emit(__add_r(__CS, __r9, __r9, __r8));
363+
emit(__srl_amt(__AL, 1, logic_rs, __r8, __r8, 1));
364+
emit(__srl_amt(__CC, 0, logic_rs, rm, rm, 1));
365+
emit(__b(__CC, -20));
366+
emit(__mov_r(__AL, rd, __r9));
367+
/* Handle the correct sign for quotient */
368+
emit(__cmp_i(__AL, __r10, 0));
369+
emit(__rsb_i(__NE, rd, 0, rd));
370+
}
327371
return;
328372
case OP_mod:
329-
emit(__div(__AL, __r8, rm, rn));
330-
emit(__mul(__AL, __r8, rm, __r8));
331-
emit(__sub_r(__AL, rd, rn, __r8));
373+
if (hard_mul_div) {
374+
emit(__div(__AL, __r8, rm, rn));
375+
emit(__mul(__AL, __r8, rm, __r8));
376+
emit(__sub_r(__AL, rd, rn, __r8));
377+
} else {
378+
/* Obtain absoulte values of dividend and divisor */
379+
emit(__srl_amt(__AL, 0, arith_rs, __r8, rn, 31));
380+
emit(__add_r(__AL, rn, rn, __r8));
381+
emit(__eor_r(__AL, rn, rn, __r8));
382+
emit(__srl_amt(__AL, 0, arith_rs, __r9, rm, 31));
383+
emit(__add_r(__AL, rm, rm, __r9));
384+
emit(__eor_r(__AL, rm, rm, __r9));
385+
emit(__mov_r(__AL, __r10, __r8));
386+
/* Unsigned integer division */
387+
emit(__zero(__r9));
388+
emit(__mov_i(__AL, __r8, 1));
389+
emit(__cmp_i(__AL, rm, 0));
390+
emit(__b(__EQ, 52));
391+
emit(__cmp_i(__AL, rn, 0));
392+
emit(__b(__EQ, 44));
393+
emit(__cmp_r(__AL, rm, rn));
394+
emit(__sll_amt(__CC, 0, logic_ls, rm, rm, 1));
395+
emit(__sll_amt(__CC, 0, logic_ls, __r8, __r8, 1));
396+
emit(__b(__CC, -12));
397+
emit(__cmp_r(__AL, rn, rm));
398+
emit(__sub_r(__CS, rn, rn, rm));
399+
emit(__add_r(__CS, __r9, __r9, __r8));
400+
emit(__srl_amt(__AL, 1, logic_rs, __r8, __r8, 1));
401+
emit(__srl_amt(__CC, 0, logic_rs, rm, rm, 1));
402+
emit(__b(__CC, -20));
403+
emit(__mov_r(__AL, rd, rn));
404+
/* Handle the correct sign for remainder */
405+
emit(__cmp_i(__AL, __r10, 0));
406+
emit(__rsb_i(__NE, rd, 0, rd));
407+
}
332408
return;
333409
case OP_lshift:
334410
emit(__sll(__AL, rd, rn, rm));

src/arm.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ typedef enum {
4747
typedef enum {
4848
__EQ = 0, /* Equal */
4949
__NE = 1, /* Not equal */
50+
__CS = 2, /* Unsigned higher or same */
51+
__CC = 3, /* Unsigned lower */
52+
__LS = 9, /* unsigned lower or same */
5053
__GE = 10, /* Signed greater than or equal */
5154
__LT = 11, /* Signed less than */
5255
__GT = 12, /* Signed greater than */
@@ -74,6 +77,13 @@ typedef enum {
7477
__pc = 15 /* program counter, r15 */
7578
} arm_reg;
7679

80+
typedef enum {
81+
logic_ls = 0, /* Logical left shift */
82+
logic_rs = 1, /* Logical right shift */
83+
arith_rs = 2, /* Arithmetic right shift */
84+
rotat_rs = 3 /* Rotate right shift */
85+
} shfit_type;
86+
7787
arm_cond_t arm_get_cond(opcode_t op)
7888
{
7989
switch (op) {
@@ -186,12 +196,34 @@ int __srl(arm_cond_t cond, arm_reg rd, arm_reg rm, arm_reg rs)
186196
rm + (1 << 4) + (1 << 5) + (rs << 8));
187197
}
188198

199+
int __srl_amt(arm_cond_t cond,
200+
int s,
201+
shfit_type shift,
202+
arm_reg rd,
203+
arm_reg rm,
204+
int amt)
205+
{
206+
return arm_encode(cond, s + (arm_mov << 1) + (0 << 5), 0, rd,
207+
rm + (0 << 4) + (shift << 5) + (amt << 7));
208+
}
209+
189210
int __sll(arm_cond_t cond, arm_reg rd, arm_reg rm, arm_reg rs)
190211
{
191212
return arm_encode(cond, 0 + (arm_mov << 1) + (0 << 5), 0, rd,
192213
rm + (1 << 4) + (0 << 5) + (rs << 8));
193214
}
194215

216+
int __sll_amt(arm_cond_t cond,
217+
int s,
218+
shfit_type shift,
219+
arm_reg rd,
220+
arm_reg rm,
221+
int amt)
222+
{
223+
return arm_encode(cond, s + (arm_mov << 1) + (0 << 5), 0, rd,
224+
rm + (0 << 4) + (shift << 5) + (amt << 7));
225+
}
226+
195227
int __add_i(arm_cond_t cond, arm_reg rd, arm_reg rs, int imm)
196228
{
197229
if (imm >= 0)
@@ -288,6 +320,11 @@ int __cmp_r(arm_cond_t cond, arm_reg r1, arm_reg r2)
288320
return __mov(cond, 0, arm_cmp, 1, r1, 0, r2);
289321
}
290322

323+
int __cmp_i(arm_cond_t cond, arm_reg rn, int imm)
324+
{
325+
return __mov(cond, 1, arm_cmp, 1, rn, 0, imm);
326+
}
327+
291328
int __teq(arm_reg rd)
292329
{
293330
return __mov(__AL, 1, arm_teq, 1, rd, 0, 0);

src/defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#define MAX_BB_DOM_SUCC 64
2626
#define MAX_GLOBAL_IR 256
2727
#define MAX_LABEL 4096
28-
#define MAX_SOURCE 278528
28+
#define MAX_SOURCE 327680
2929
#define MAX_CODE 262144
3030
#define MAX_DATA 262144
3131
#define MAX_SYMTAB 65536

src/globals.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ int find_trie(trie_t *trie, char *name)
132132
/* options */
133133

134134
int dump_ir = 0;
135+
int hard_mul_div = 0;
135136

136137
/**
137138
* find_type() - Find the type by the given name.

src/main.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ int main(int argc, char *argv[])
5151
for (int i = 1; i < argc; i++) {
5252
if (!strcmp(argv[i], "--dump-ir"))
5353
dump_ir = 1;
54+
else if (!strcmp(argv[i], "+m"))
55+
hard_mul_div = 1;
5456
else if (!strcmp(argv[i], "--no-libc"))
5557
libc = 0;
5658
else if (!strcmp(argv[i], "-o")) {
@@ -66,7 +68,9 @@ int main(int argc, char *argv[])
6668

6769
if (!in) {
6870
printf("Missing source file!\n");
69-
printf("Usage: shecc [-o output] [--dump-ir] [--no-libc] <input.c>\n");
71+
printf(
72+
"Usage: shecc [-o output] [+m] [--dump-ir] [--no-libc] "
73+
"<input.c>\n");
7074
return -1;
7175
}
7276

0 commit comments

Comments
 (0)