diff options
| -rw-r--r-- | dynasm/dasm_arm.h | 17 | ||||
| -rw-r--r-- | dynasm/dasm_arm.lua | 267 |
2 files changed, 235 insertions, 49 deletions
diff --git a/dynasm/dasm_arm.h b/dynasm/dasm_arm.h index b770c2df..d49ecae0 100644 --- a/dynasm/dasm_arm.h +++ b/dynasm/dasm_arm.h | |||
| @@ -22,7 +22,7 @@ enum { | |||
| 22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, | 22 | DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, |
| 23 | /* The following actions also have an argument. */ | 23 | /* The following actions also have an argument. */ |
| 24 | DASM_REL_PC, DASM_LABEL_PC, | 24 | DASM_REL_PC, DASM_LABEL_PC, |
| 25 | DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, | 25 | DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8, |
| 26 | DASM__MAX | 26 | DASM__MAX |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| @@ -250,6 +250,9 @@ void dasm_put(Dst_DECL, int start, ...) | |||
| 250 | #endif | 250 | #endif |
| 251 | b[pos++] = n; | 251 | b[pos++] = n; |
| 252 | break; | 252 | break; |
| 253 | case DASM_IMMV8: | ||
| 254 | CK((n & 3) == 0, RANGE_I); | ||
| 255 | n >>= 2; | ||
| 253 | case DASM_IMML8: | 256 | case DASM_IMML8: |
| 254 | case DASM_IMML12: | 257 | case DASM_IMML12: |
| 255 | CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) : | 258 | CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) : |
| @@ -316,7 +319,7 @@ int dasm_link(Dst_DECL, size_t *szp) | |||
| 316 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; | 319 | case DASM_REL_LG: case DASM_REL_PC: pos++; break; |
| 317 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; | 320 | case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; |
| 318 | case DASM_IMM: case DASM_IMM12: case DASM_IMM16: | 321 | case DASM_IMM: case DASM_IMM12: case DASM_IMM16: |
| 319 | case DASM_IMML8: case DASM_IMML12: pos++; break; | 322 | case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break; |
| 320 | } | 323 | } |
| 321 | } | 324 | } |
| 322 | stop: (void)0; | 325 | stop: (void)0; |
| @@ -377,9 +380,13 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 377 | } else if ((ins & 0x1000)) { | 380 | } else if ((ins & 0x1000)) { |
| 378 | CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); | 381 | CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); |
| 379 | goto patchimml8; | 382 | goto patchimml8; |
| 380 | } else { | 383 | } else if ((ins & 0x2000) == 0) { |
| 381 | CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); | 384 | CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); |
| 382 | goto patchimml12; | 385 | goto patchimml; |
| 386 | } else { | ||
| 387 | CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL); | ||
| 388 | n >>= 2; | ||
| 389 | goto patchimml; | ||
| 383 | } | 390 | } |
| 384 | break; | 391 | break; |
| 385 | case DASM_LABEL_LG: | 392 | case DASM_LABEL_LG: |
| @@ -399,7 +406,7 @@ int dasm_encode(Dst_DECL, void *buffer) | |||
| 399 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : | 406 | cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : |
| 400 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); | 407 | ((-n & 0x0f) | ((-n & 0xf0) << 4)); |
| 401 | break; | 408 | break; |
| 402 | case DASM_IMML12: patchimml12: | 409 | case DASM_IMML12: case DASM_IMMV8: patchimml: |
| 403 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); | 410 | cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); |
| 404 | break; | 411 | break; |
| 405 | default: *cp++ = ins; break; | 412 | default: *cp++ = ins; break; |
diff --git a/dynasm/dasm_arm.lua b/dynasm/dasm_arm.lua index 4735f323..11701691 100644 --- a/dynasm/dasm_arm.lua +++ b/dynasm/dasm_arm.lua | |||
| @@ -39,7 +39,7 @@ local wline, werror, wfatal, wwarn | |||
| 39 | local action_names = { | 39 | local action_names = { |
| 40 | "STOP", "SECTION", "ESC", "REL_EXT", | 40 | "STOP", "SECTION", "ESC", "REL_EXT", |
| 41 | "ALIGN", "REL_LG", "LABEL_LG", | 41 | "ALIGN", "REL_LG", "LABEL_LG", |
| 42 | "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", | 42 | "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", "IMMV8", |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | -- Maximum number of section buffer positions for dasm_put(). | 45 | -- Maximum number of section buffer positions for dasm_put(). |
| @@ -405,14 +405,14 @@ local map_op = { | |||
| 405 | strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE | 405 | strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE |
| 406 | ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL", | 406 | ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL", |
| 407 | 407 | ||
| 408 | ldm_2 = "e8900000nR", ldmia_2 = "e8900000nR", ldmfd_2 = "e8900000nR", | 408 | ldm_2 = "e8900000oR", ldmia_2 = "e8900000oR", ldmfd_2 = "e8900000oR", |
| 409 | ldmda_2 = "e8100000nR", ldmfa_2 = "e8100000nR", | 409 | ldmda_2 = "e8100000oR", ldmfa_2 = "e8100000oR", |
| 410 | ldmdb_2 = "e9100000nR", ldmea_2 = "e9100000nR", | 410 | ldmdb_2 = "e9100000oR", ldmea_2 = "e9100000oR", |
| 411 | ldmib_2 = "e9900000nR", ldmed_2 = "e9900000nR", | 411 | ldmib_2 = "e9900000oR", ldmed_2 = "e9900000oR", |
| 412 | stm_2 = "e8800000nR", stmia_2 = "e8800000nR", stmfd_2 = "e8800000nR", | 412 | stm_2 = "e8800000oR", stmia_2 = "e8800000oR", stmfd_2 = "e8800000oR", |
| 413 | stmda_2 = "e8000000nR", stmfa_2 = "e8000000nR", | 413 | stmda_2 = "e8000000oR", stmfa_2 = "e8000000oR", |
| 414 | stmdb_2 = "e9000000nR", stmea_2 = "e9000000nR", | 414 | stmdb_2 = "e9000000oR", stmea_2 = "e9000000oR", |
| 415 | stmib_2 = "e9800000nR", stmed_2 = "e9800000nR", | 415 | stmib_2 = "e9800000oR", stmed_2 = "e9800000oR", |
| 416 | pop_1 = "e8bd0000R", push_1 = "e92d0000R", | 416 | pop_1 = "e8bd0000R", push_1 = "e92d0000R", |
| 417 | 417 | ||
| 418 | -- Branch instructions. | 418 | -- Branch instructions. |
| @@ -428,9 +428,89 @@ local map_op = { | |||
| 428 | svc_1 = "ef000000T", swi_1 = "ef000000T", | 428 | svc_1 = "ef000000T", swi_1 = "ef000000T", |
| 429 | ud_0 = "e7f001f0", | 429 | ud_0 = "e7f001f0", |
| 430 | 430 | ||
| 431 | -- NYI: Advanced SIMD and VFP instructions. | 431 | -- VFP instructions. |
| 432 | 432 | ["vadd.f32_3"] = "ee300a00dnm", | |
| 433 | -- NYI instructions, since I have no need for them right now: | 433 | ["vadd.f64_3"] = "ee300b00Gdnm", |
| 434 | ["vsub.f32_3"] = "ee300a40dnm", | ||
| 435 | ["vsub.f64_3"] = "ee300b40Gdnm", | ||
| 436 | ["vmul.f32_3"] = "ee200a00dnm", | ||
| 437 | ["vmul.f64_3"] = "ee200b00Gdnm", | ||
| 438 | ["vnmul.f32_3"] = "ee200a40dnm", | ||
| 439 | ["vnmul.f64_3"] = "ee200b40Gdnm", | ||
| 440 | ["vmla.f32_3"] = "ee000a00dnm", | ||
| 441 | ["vmla.f64_3"] = "ee000b00Gdnm", | ||
| 442 | ["vmls.f32_3"] = "ee000a40dnm", | ||
| 443 | ["vmls.f64_3"] = "ee000b40Gdnm", | ||
| 444 | ["vnmla.f32_3"] = "ee100a40dnm", | ||
| 445 | ["vnmla.f64_3"] = "ee100b40Gdnm", | ||
| 446 | ["vnmls.f32_3"] = "ee100a00dnm", | ||
| 447 | ["vnmls.f64_3"] = "ee100b00Gdnm", | ||
| 448 | ["vdiv.f32_3"] = "ee800a00dnm", | ||
| 449 | ["vdiv.f64_3"] = "ee800b00Gdnm", | ||
| 450 | |||
| 451 | ["vabs.f32_2"] = "eeb00ac0dm", | ||
| 452 | ["vabs.f64_2"] = "eeb00bc0Gdm", | ||
| 453 | ["vneg.f32_2"] = "eeb10a40dm", | ||
| 454 | ["vneg.f64_2"] = "eeb10b40Gdm", | ||
| 455 | ["vsqrt.f32_2"] = "eeb10ac0dm", | ||
| 456 | ["vsqrt.f64_2"] = "eeb10bc0Gdm", | ||
| 457 | ["vcmp.f32_2"] = "eeb40a40dm", | ||
| 458 | ["vcmp.f64_2"] = "eeb40b40Gdm", | ||
| 459 | ["vcmpe.f32_2"] = "eeb40ac0dm", | ||
| 460 | ["vcmpe.f64_2"] = "eeb40bc0Gdm", | ||
| 461 | ["vcmpz.f32_1"] = "eeb50a40d", | ||
| 462 | ["vcmpz.f64_1"] = "eeb50b40Gd", | ||
| 463 | ["vcmpze.f32_1"] = "eeb50ac0d", | ||
| 464 | ["vcmpze.f64_1"] = "eeb50bc0Gd", | ||
| 465 | |||
| 466 | vldr_2 = "ed100a00dl|ed100b00Gdl", | ||
| 467 | vstr_2 = "ed000a00dl|ed000b00Gdl", | ||
| 468 | vldm_2 = "ec900a00or", | ||
| 469 | vldmia_2 = "ec900a00or", | ||
| 470 | vldmdb_2 = "ed100a00or", | ||
| 471 | vpop_1 = "ecbd0a00r", | ||
| 472 | vstm_2 = "ec800a00or", | ||
| 473 | vstmia_2 = "ec800a00or", | ||
| 474 | vstmdb_2 = "ed000a00or", | ||
| 475 | vpush_1 = "ed2d0a00r", | ||
| 476 | |||
| 477 | ["vmov.f32_2"] = "eeb00a40dm|eeb00a00dY", -- #imm is VFPv3 only | ||
| 478 | ["vmov.f64_2"] = "eeb00b40Gdm|eeb00b00GdY", -- #imm is VFPv3 only | ||
| 479 | vmov_2 = "ee100a10Dn|ee000a10nD", | ||
| 480 | vmov_3 = "ec500a10DNm|ec400a10mDN|ec500b10GDNm|ec400b10GmDN", | ||
| 481 | |||
| 482 | vmrs_0 = "eef1fa10", | ||
| 483 | vmrs_1 = "eef10a10D", | ||
| 484 | vmsr_1 = "eee10a10D", | ||
| 485 | |||
| 486 | ["vcvt.s32.f32_2"] = "eebd0ac0dm", | ||
| 487 | ["vcvt.s32.f64_2"] = "eebd0bc0dGm", | ||
| 488 | ["vcvt.u32.f32_2"] = "eebc0ac0dm", | ||
| 489 | ["vcvt.u32.f64_2"] = "eebc0bc0dGm", | ||
| 490 | ["vcvtr.s32.f32_2"] = "eebd0a40dm", | ||
| 491 | ["vcvtr.s32.f64_2"] = "eebd0b40dGm", | ||
| 492 | ["vcvtr.u32.f32_2"] = "eebc0a40dm", | ||
| 493 | ["vcvtr.u32.f64_2"] = "eebc0b40dGm", | ||
| 494 | ["vcvt.f32.s32_2"] = "eeb80ac0dm", | ||
| 495 | ["vcvt.f64.s32_2"] = "eeb80bc0GdFm", | ||
| 496 | ["vcvt.f32.u32_2"] = "eeb80a40dm", | ||
| 497 | ["vcvt.f64.u32_2"] = "eeb80b40GdFm", | ||
| 498 | ["vcvt.f32.f64_2"] = "eeb70bc0dGm", | ||
| 499 | ["vcvt.f64.f32_2"] = "eeb70ac0GdFm", | ||
| 500 | |||
| 501 | -- VFPv4 only: | ||
| 502 | ["vfma.f32_3"] = "eea00a00dnm", | ||
| 503 | ["vfma.f64_3"] = "eea00b00Gdnm", | ||
| 504 | ["vfms.f32_3"] = "eea00a40dnm", | ||
| 505 | ["vfms.f64_3"] = "eea00b40Gdnm", | ||
| 506 | ["vfnma.f32_3"] = "ee900a40dnm", | ||
| 507 | ["vfnma.f64_3"] = "ee900b40Gdnm", | ||
| 508 | ["vfnms.f32_3"] = "ee900a00dnm", | ||
| 509 | ["vfnms.f64_3"] = "ee900b00Gdnm", | ||
| 510 | |||
| 511 | -- NYI: Advanced SIMD instructions. | ||
| 512 | |||
| 513 | -- NYI: I have no need for these instructions right now: | ||
| 434 | -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh | 514 | -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh |
| 435 | -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe | 515 | -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe |
| 436 | -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb | 516 | -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb |
| @@ -476,6 +556,18 @@ local function parse_gpr_pm(expr) | |||
| 476 | return parse_gpr(expr2), (pm == "-") | 556 | return parse_gpr(expr2), (pm == "-") |
| 477 | end | 557 | end |
| 478 | 558 | ||
| 559 | local function parse_vr(expr, tp) | ||
| 560 | local t, r = match(expr, "^([sd])([0-9]+)$") | ||
| 561 | if t == tp then | ||
| 562 | r = tonumber(r) | ||
| 563 | if r <= 31 then | ||
| 564 | if t == "s" then return shr(r, 1), band(r, 1) end | ||
| 565 | return band(r, 15), shr(r, 4) | ||
| 566 | end | ||
| 567 | end | ||
| 568 | werror("bad register name `"..expr.."'") | ||
| 569 | end | ||
| 570 | |||
| 479 | local function parse_reglist(reglist) | 571 | local function parse_reglist(reglist) |
| 480 | reglist = match(reglist, "^{%s*([^}]*)}$") | 572 | reglist = match(reglist, "^{%s*([^}]*)}$") |
| 481 | if not reglist then werror("register list expected") end | 573 | if not reglist then werror("register list expected") end |
| @@ -490,6 +582,21 @@ local function parse_reglist(reglist) | |||
| 490 | return rr | 582 | return rr |
| 491 | end | 583 | end |
| 492 | 584 | ||
| 585 | local function parse_vrlist(reglist) | ||
| 586 | local ta, ra, tb, rb = match(reglist, | ||
| 587 | "^{%s*([sd])([0-9]+)%s*%-%s*([sd])([0-9]+)%s*}$") | ||
| 588 | ra, rb = tonumber(ra), tonumber(rb) | ||
| 589 | if ta and ta == tb and ra and rb and ra <= 31 and rb <= 31 and ra <= rb then | ||
| 590 | local nr = rb+1 - ra | ||
| 591 | if ta == "s" then | ||
| 592 | return shl(shr(ra,1),12)+shl(band(ra,1),22) + nr | ||
| 593 | else | ||
| 594 | return shl(band(ra,15),12)+shl(shr(ra,4),22) + nr*2 + 0x100 | ||
| 595 | end | ||
| 596 | end | ||
| 597 | werror("register list expected") | ||
| 598 | end | ||
| 599 | |||
| 493 | local function parse_imm(imm, bits, shift, scale, signed) | 600 | local function parse_imm(imm, bits, shift, scale, signed) |
| 494 | imm = match(imm, "^#(.*)$") | 601 | imm = match(imm, "^#(.*)$") |
| 495 | if not imm then werror("expected immediate operand") end | 602 | if not imm then werror("expected immediate operand") end |
| @@ -680,81 +787,132 @@ local function parse_load(params, nparams, n, op) | |||
| 680 | return op | 787 | return op |
| 681 | end | 788 | end |
| 682 | 789 | ||
| 790 | local function parse_vload(q) | ||
| 791 | local reg, imm = match(q, "^%[%s*([^,%s]*)%s*(.*)%]$") | ||
| 792 | if reg then | ||
| 793 | local d = shl(parse_gpr(reg), 16) | ||
| 794 | if imm == "" then return d end | ||
| 795 | imm = match(imm, "^,%s*#(.*)$") | ||
| 796 | if imm then | ||
| 797 | local n = tonumber(imm) | ||
| 798 | if n then | ||
| 799 | if n >= -1020 and n <= 1020 and n%4 == 0 then | ||
| 800 | return d + (n >= 0 and n/4+0x00800000 or -n/4) | ||
| 801 | end | ||
| 802 | werror("out of range immediate `"..imm.."'") | ||
| 803 | else | ||
| 804 | waction("IMMV8", 32768 + 32*8, imm) | ||
| 805 | return d | ||
| 806 | end | ||
| 807 | end | ||
| 808 | else | ||
| 809 | if match(q, "^[<>=%-]") or match(q, "^extern%s+") then | ||
| 810 | local mode, n, s = parse_label(q, false) | ||
| 811 | waction("REL_"..mode, n + 0x2800, s, 1) | ||
| 812 | return 15 * 65536 | ||
| 813 | end | ||
| 814 | local reg, tailr = match(q, "^([%w_:]+)%s*(.*)$") | ||
| 815 | if reg and tailr ~= "" then | ||
| 816 | local d, tp = parse_gpr(reg) | ||
| 817 | if tp then | ||
| 818 | waction("IMMV8", 32768 + 32*8, format(tp.ctypefmt, tailr)) | ||
| 819 | return shl(d, 16) | ||
| 820 | end | ||
| 821 | end | ||
| 822 | end | ||
| 823 | werror("expected address operand") | ||
| 824 | end | ||
| 825 | |||
| 683 | ------------------------------------------------------------------------------ | 826 | ------------------------------------------------------------------------------ |
| 684 | 827 | ||
| 685 | -- Handle opcodes defined with template strings. | 828 | -- Handle opcodes defined with template strings. |
| 686 | map_op[".template__"] = function(params, template, nparams) | 829 | local function parse_template(params, template, nparams, pos) |
| 687 | if not params then return sub(template, 9) end | ||
| 688 | local op = tonumber(sub(template, 1, 8), 16) | 830 | local op = tonumber(sub(template, 1, 8), 16) |
| 689 | local n = 1 | 831 | local n = 1 |
| 690 | 832 | local vr = "s" | |
| 691 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
| 692 | -- A single opcode needs a maximum of 3 positions. | ||
| 693 | if secpos+3 > maxsecpos then wflush() end | ||
| 694 | local pos = wpos() | ||
| 695 | 833 | ||
| 696 | -- Process each character. | 834 | -- Process each character. |
| 697 | for p in gmatch(sub(template, 9), ".") do | 835 | for p in gmatch(sub(template, 9), ".") do |
| 836 | local q = params[n] | ||
| 698 | if p == "D" then | 837 | if p == "D" then |
| 699 | op = op + shl(parse_gpr(params[n]), 12); n = n + 1 | 838 | op = op + shl(parse_gpr(q), 12); n = n + 1 |
| 700 | elseif p == "N" then | 839 | elseif p == "N" then |
| 701 | op = op + shl(parse_gpr(params[n]), 16); n = n + 1 | 840 | op = op + shl(parse_gpr(q), 16); n = n + 1 |
| 702 | elseif p == "S" then | 841 | elseif p == "S" then |
| 703 | op = op + shl(parse_gpr(params[n]), 8); n = n + 1 | 842 | op = op + shl(parse_gpr(q), 8); n = n + 1 |
| 704 | elseif p == "M" then | 843 | elseif p == "M" then |
| 705 | op = op + parse_gpr(params[n]); n = n + 1 | 844 | op = op + parse_gpr(q); n = n + 1 |
| 845 | elseif p == "d" then | ||
| 846 | local r,h = parse_vr(q, vr); op = op+shl(r,12)+shl(h,22); n = n + 1 | ||
| 847 | elseif p == "n" then | ||
| 848 | local r,h = parse_vr(q, vr); op = op+shl(r,16)+shl(h,7); n = n + 1 | ||
| 849 | elseif p == "m" then | ||
| 850 | local r,h = parse_vr(q, vr); op = op+r+shl(h,5); n = n + 1 | ||
| 706 | elseif p == "P" then | 851 | elseif p == "P" then |
| 707 | local imm = match(params[n], "^#(.*)$") | 852 | local imm = match(q, "^#(.*)$") |
| 708 | if imm then | 853 | if imm then |
| 709 | op = op + parse_imm12(imm) + 0x02000000 | 854 | op = op + parse_imm12(imm) + 0x02000000 |
| 710 | else | 855 | else |
| 711 | op = op + parse_gpr(params[n]) | 856 | op = op + parse_gpr(q) |
| 712 | end | 857 | end |
| 713 | n = n + 1 | 858 | n = n + 1 |
| 714 | elseif p == "p" then | 859 | elseif p == "p" then |
| 715 | op = op + parse_shift(params[n], true); n = n + 1 | 860 | op = op + parse_shift(q, true); n = n + 1 |
| 716 | elseif p == "L" then | 861 | elseif p == "L" then |
| 717 | op = parse_load(params, nparams, n, op) | 862 | op = parse_load(params, nparams, n, op) |
| 863 | elseif p == "l" then | ||
| 864 | op = op + parse_vload(q) | ||
| 718 | elseif p == "B" then | 865 | elseif p == "B" then |
| 719 | local mode, n, s = parse_label(params[n], false) | 866 | local mode, n, s = parse_label(q, false) |
| 720 | waction("REL_"..mode, n, s, 1) | 867 | waction("REL_"..mode, n, s, 1) |
| 721 | elseif p == "C" then -- blx gpr vs. blx label. | 868 | elseif p == "C" then -- blx gpr vs. blx label. |
| 722 | local p = params[n] | 869 | if match(q, "^([%w_]+):(r1?[0-9])$") or match(q, "^r(1?[0-9])$") then |
| 723 | if match(p, "^([%w_]+):(r1?[0-9])$") or match(p, "^r(1?[0-9])$") then | 870 | op = op + parse_gpr(q) |
| 724 | op = op + parse_gpr(p) | ||
| 725 | else | 871 | else |
| 726 | if op < 0xe0000000 then werror("unconditional instruction") end | 872 | if op < 0xe0000000 then werror("unconditional instruction") end |
| 727 | local mode, n, s = parse_label(p, false) | 873 | local mode, n, s = parse_label(q, false) |
| 728 | waction("REL_"..mode, n, s, 1) | 874 | waction("REL_"..mode, n, s, 1) |
| 729 | op = 0xfa000000 | 875 | op = 0xfa000000 |
| 730 | end | 876 | end |
| 731 | elseif p == "n" then | 877 | elseif p == "F" then |
| 732 | local r, wb = match(params[n], "^([^!]*)(!?)$") | 878 | vr = "s" |
| 879 | elseif p == "G" then | ||
| 880 | vr = "d" | ||
| 881 | elseif p == "o" then | ||
| 882 | local r, wb = match(q, "^([^!]*)(!?)$") | ||
| 733 | op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0) | 883 | op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0) |
| 734 | n = n + 1 | 884 | n = n + 1 |
| 735 | elseif p == "R" then | 885 | elseif p == "R" then |
| 736 | op = op + parse_reglist(params[n]); n = n + 1 | 886 | op = op + parse_reglist(q); n = n + 1 |
| 887 | elseif p == "r" then | ||
| 888 | op = op + parse_vrlist(q); n = n + 1 | ||
| 737 | elseif p == "W" then | 889 | elseif p == "W" then |
| 738 | op = op + parse_imm16(params[n]); n = n + 1 | 890 | op = op + parse_imm16(q); n = n + 1 |
| 739 | elseif p == "v" then | 891 | elseif p == "v" then |
| 740 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 | 892 | op = op + parse_imm(q, 5, 7, 0, false); n = n + 1 |
| 741 | elseif p == "w" then | 893 | elseif p == "w" then |
| 742 | local imm = match(params[n], "^#(.*)$") | 894 | local imm = match(q, "^#(.*)$") |
| 743 | if imm then | 895 | if imm then |
| 744 | op = op + parse_imm(params[n], 5, 7, 0, false); n = n + 1 | 896 | op = op + parse_imm(q, 5, 7, 0, false); n = n + 1 |
| 745 | else | 897 | else |
| 746 | op = op + shl(parse_gpr(params[n]), 8) + 16 | 898 | op = op + shl(parse_gpr(q), 8) + 16 |
| 747 | end | 899 | end |
| 748 | elseif p == "X" then | 900 | elseif p == "X" then |
| 749 | op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 | 901 | op = op + parse_imm(q, 5, 16, 0, false); n = n + 1 |
| 902 | elseif p == "Y" then | ||
| 903 | local imm = tonumber(match(q, "^#(.*)$")); n = n + 1 | ||
| 904 | if not imm or shr(imm, 8) ~= 0 then | ||
| 905 | werror("bad immediate operand") | ||
| 906 | end | ||
| 907 | op = op + shl(band(imm, 0xf0), 12) + band(imm, 0x0f) | ||
| 750 | elseif p == "K" then | 908 | elseif p == "K" then |
| 751 | local imm = tonumber(match(params[n], "^#(.*)$")); n = n + 1 | 909 | local imm = tonumber(match(q, "^#(.*)$")); n = n + 1 |
| 752 | if not imm or shr(imm, 16) ~= 0 then | 910 | if not imm or shr(imm, 16) ~= 0 then |
| 753 | werror("bad immediate operand") | 911 | werror("bad immediate operand") |
| 754 | end | 912 | end |
| 755 | op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f) | 913 | op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f) |
| 756 | elseif p == "T" then | 914 | elseif p == "T" then |
| 757 | op = op + parse_imm(params[n], 24, 0, 0, false); n = n + 1 | 915 | op = op + parse_imm(q, 24, 0, 0, false); n = n + 1 |
| 758 | elseif p == "s" then | 916 | elseif p == "s" then |
| 759 | -- Ignored. | 917 | -- Ignored. |
| 760 | else | 918 | else |
| @@ -764,6 +922,27 @@ map_op[".template__"] = function(params, template, nparams) | |||
| 764 | wputpos(pos, op) | 922 | wputpos(pos, op) |
| 765 | end | 923 | end |
| 766 | 924 | ||
| 925 | map_op[".template__"] = function(params, template, nparams) | ||
| 926 | if not params then return sub(template, 9) end | ||
| 927 | |||
| 928 | -- Limit number of section buffer positions used by a single dasm_put(). | ||
| 929 | -- A single opcode needs a maximum of 3 positions. | ||
| 930 | if secpos+3 > maxsecpos then wflush() end | ||
| 931 | local pos = wpos() | ||
| 932 | local apos, spos = #actargs, secpos | ||
| 933 | |||
| 934 | local ok, err | ||
| 935 | for t in gmatch(template, "[^|]+") do | ||
| 936 | ok, err = pcall(parse_template, params, t, nparams, pos) | ||
| 937 | if ok then return end | ||
| 938 | secpos = spos | ||
| 939 | actargs[apos+1] = nil | ||
| 940 | actargs[apos+2] = nil | ||
| 941 | actargs[apos+3] = nil | ||
| 942 | end | ||
| 943 | error(err, 0) | ||
| 944 | end | ||
| 945 | |||
| 767 | ------------------------------------------------------------------------------ | 946 | ------------------------------------------------------------------------------ |
| 768 | 947 | ||
| 769 | -- Pseudo-opcode to mark the position where the action list is to be emitted. | 948 | -- Pseudo-opcode to mark the position where the action list is to be emitted. |
| @@ -923,10 +1102,10 @@ function _M.mergemaps(map_coreop, map_def) | |||
| 923 | setmetatable(map_op, { __index = function(t, k) | 1102 | setmetatable(map_op, { __index = function(t, k) |
| 924 | local v = map_coreop[k] | 1103 | local v = map_coreop[k] |
| 925 | if v then return v end | 1104 | if v then return v end |
| 926 | local cc = sub(k, -4, -3) | 1105 | local k1, cc, k2 = match(k, "^(.-)(..)([._].*)$") |
| 927 | local cv = map_cond[cc] | 1106 | local cv = map_cond[cc] |
| 928 | if cv then | 1107 | if cv then |
| 929 | local v = rawget(t, sub(k, 1, -5)..sub(k, -2)) | 1108 | local v = rawget(t, k1..k2) |
| 930 | if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end | 1109 | if type(v) == "string" then return format("%x%s", cv, sub(v, 2)) end |
| 931 | end | 1110 | end |
| 932 | end }) | 1111 | end }) |
