History

arm-asm: Add mul, mla, smull, umull, smlal, umlal

Danny Milosavljevic committed 5 years ago

Commit 82663d31 parent c4e13c12 files · +190 −0Browse files

Unified · Split

2 files
  1. arm-asm.c +175 −0
  2. arm-tok.h +15 −0
arm-asm.c+175−0
@@ -286,6 +286,165 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) · 285 unmodified lines
286286 }
287287 }
288288
289+static void asm_multiplication_opcode(TCCState *s1, int token)
290+{
291+ Operand ops[4];
292+ int nb_ops = 0;
293+ uint32_t opcode = 0x90;
294+
295+ for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
296+ parse_operand(s1, &ops[nb_ops]);
297+ if (tok != ',') {
298+ ++nb_ops;
299+ break;
300+ }
301+ next(); // skip ','
302+ }
303+ if (nb_ops < 2)
304+ expect("at least two operands");
305+ else if (nb_ops == 2) {
306+ switch (ARM_INSTRUCTION_GROUP(token)) {
307+ case TOK_ASM_mulseq:
308+ case TOK_ASM_muleq:
309+ memcpy(&ops[2], &ops[0], sizeof(ops[1])); // ARM is actually like this!
310+ break;
311+ default:
312+ memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2]
313+ memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit
314+ }
315+ nb_ops = 3;
316+ }
317+
318+ // multiply (special case):
319+ // operands:
320+ // Rd: bits 19...16
321+ // Rm: bits 3...0
322+ // Rs: bits 11...8
323+ // Rn: bits 15...12
324+
325+ if (ops[0].type == OP_REG32)
326+ opcode |= ops[0].reg << 16;
327+ else
328+ expect("(destination operand) register");
329+ if (ops[1].type == OP_REG32)
330+ opcode |= ops[1].reg;
331+ else
332+ expect("(first source operand) register");
333+ if (ops[2].type == OP_REG32)
334+ opcode |= ops[2].reg << 8;
335+ else
336+ expect("(second source operand) register");
337+ if (nb_ops > 3) {
338+ if (ops[3].type == OP_REG32)
339+ opcode |= ops[3].reg << 12;
340+ else
341+ expect("(third source operand) register");
342+ }
343+
344+ switch (ARM_INSTRUCTION_GROUP(token)) {
345+ case TOK_ASM_mulseq:
346+ opcode |= 1 << 20; // Status
347+ /* fallthrough */
348+ case TOK_ASM_muleq:
349+ if (nb_ops != 3)
350+ expect("three operands");
351+ else {
352+ asm_emit_opcode(token, opcode);
353+ }
354+ break;
355+ case TOK_ASM_mlaseq:
356+ opcode |= 1 << 20; // Status
357+ /* fallthrough */
358+ case TOK_ASM_mlaeq:
359+ if (nb_ops != 4)
360+ expect("four operands");
361+ else {
362+ opcode |= 1 << 21; // Accumulate
363+ asm_emit_opcode(token, opcode);
364+ }
365+ break;
366+ default:
367+ expect("known multiplication instruction");
368+ }
369+}
370+
371+static void asm_long_multiplication_opcode(TCCState *s1, int token)
372+{
373+ Operand ops[4];
374+ int nb_ops = 0;
375+ uint32_t opcode = 0x90 | (1 << 23);
376+
377+ for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) {
378+ parse_operand(s1, &ops[nb_ops]);
379+ if (tok != ',') {
380+ ++nb_ops;
381+ break;
382+ }
383+ next(); // skip ','
384+ }
385+ if (nb_ops != 4) {
386+ expect("four operands");
387+ return;
388+ }
389+
390+ // long multiply (special case):
391+ // operands:
392+ // RdLo: bits 15...12
393+ // RdHi: bits 19...16
394+ // Rs: bits 11...8
395+ // Rm: bits 3...0
396+
397+ if (ops[0].type == OP_REG32)
398+ opcode |= ops[0].reg << 12;
399+ else
400+ expect("(destination lo accumulator) register");
401+ if (ops[1].type == OP_REG32)
402+ opcode |= ops[1].reg << 16;
403+ else
404+ expect("(destination hi accumulator) register");
405+ if (ops[2].type == OP_REG32)
406+ opcode |= ops[2].reg;
407+ else
408+ expect("(first source operand) register");
409+ if (ops[3].type == OP_REG32)
410+ opcode |= ops[3].reg << 8;
411+ else
412+ expect("(second source operand) register");
413+
414+ switch (ARM_INSTRUCTION_GROUP(token)) {
415+ case TOK_ASM_smullseq:
416+ opcode |= 1 << 20; // Status
417+ /* fallthrough */
418+ case TOK_ASM_smulleq:
419+ opcode |= 1 << 22; // signed
420+ asm_emit_opcode(token, opcode);
421+ break;
422+ case TOK_ASM_umullseq:
423+ opcode |= 1 << 20; // Status
424+ /* fallthrough */
425+ case TOK_ASM_umulleq:
426+ asm_emit_opcode(token, opcode);
427+ break;
428+ case TOK_ASM_smlalseq:
429+ opcode |= 1 << 20; // Status
430+ /* fallthrough */
431+ case TOK_ASM_smlaleq:
432+ opcode |= 1 << 22; // signed
433+ opcode |= 1 << 21; // Accumulate
434+ asm_emit_opcode(token, opcode);
435+ break;
436+ case TOK_ASM_umlalseq:
437+ opcode |= 1 << 20; // Status
438+ /* fallthrough */
439+ case TOK_ASM_umlaleq:
440+ opcode |= 1 << 21; // Accumulate
441+ asm_emit_opcode(token, opcode);
442+ break;
443+ default:
444+ expect("known long multiplication instruction");
445+ }
446+}
447+
289448 ST_FUNC void asm_opcode(TCCState *s1, int token)
290449 {
291450 while (token == TOK_LINEFEED) {
@@ -315,6 +474,22 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 23 unmodified lines
315474 case TOK_ASM_uxtbeq:
316475 case TOK_ASM_uxtheq:
317476 return asm_binary_opcode(s1, token);
477+
478+ case TOK_ASM_muleq:
479+ case TOK_ASM_mulseq:
480+ case TOK_ASM_mlaeq:
481+ case TOK_ASM_mlaseq:
482+ return asm_multiplication_opcode(s1, token);
483+
484+ case TOK_ASM_smulleq:
485+ case TOK_ASM_smullseq:
486+ case TOK_ASM_umulleq:
487+ case TOK_ASM_umullseq:
488+ case TOK_ASM_smlaleq:
489+ case TOK_ASM_smlalseq:
490+ case TOK_ASM_umlaleq:
491+ case TOK_ASM_umlalseq:
492+ return asm_long_multiplication_opcode(s1, token);
318493 default:
319494 expect("known instruction");
320495 }
arm-tok.h+15−0
@@ -66,6 +66,21 @@ · 65 unmodified lines
6666 DEF_ASM_CONDED(uxtb)
6767 DEF_ASM_CONDED(uxth)
6868
69+ /* multiplication */
70+
71+ DEF_ASM_CONDED(mul)
72+ DEF_ASM_CONDED(muls)
73+ DEF_ASM_CONDED(mla)
74+ DEF_ASM_CONDED(mlas)
75+ DEF_ASM_CONDED(smull)
76+ DEF_ASM_CONDED(smulls)
77+ DEF_ASM_CONDED(umull)
78+ DEF_ASM_CONDED(umulls)
79+ DEF_ASM_CONDED(smlal)
80+ DEF_ASM_CONDED(smlals)
81+ DEF_ASM_CONDED(umlal)
82+ DEF_ASM_CONDED(umlals)
83+
6984 /* instruction macros */
7085
7186 DEF_ASM_CONDED(push)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t