145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LC-3b architecture description
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *  Copyright (C) 2003-2007  Peter Johnson
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met:
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer.
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    notice, this list of conditions and the following disclaimer in the
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *    documentation and/or other materials provided with the distribution.
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE.
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <util.h>
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm.h>
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "lc3barch.h"
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_arch_module yasm_lc3b_LTX_arch;
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic /*@only@*/ yasm_arch *
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_create(const char *machine, const char *parser,
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /*@out@*/ yasm_arch_create_error *error)
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_arch_base *arch;
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *error = YASM_ARCH_CREATE_OK;
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm__strcasecmp(machine, "lc3b") != 0) {
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *error = YASM_ARCH_CREATE_BAD_MACHINE;
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (yasm__strcasecmp(parser, "nasm") != 0) {
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *error = YASM_ARCH_CREATE_BAD_PARSER;
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return NULL;
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    arch = yasm_xmalloc(sizeof(yasm_arch_base));
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    arch->module = &yasm_lc3b_LTX_arch;
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return (yasm_arch *)arch;
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_destroy(/*@only@*/ yasm_arch *arch)
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(arch);
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const char *
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_get_machine(/*@unused@*/ const yasm_arch *arch)
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return "lc3b";
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned int
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_get_address_size(/*@unused@*/ const yasm_arch *arch)
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 16;
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_set_var(yasm_arch *arch, const char *var, unsigned long val)
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const unsigned char **
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_get_fill(const yasm_arch *arch)
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* NOP pattern is all 0's per LC-3b Assembler 3.50 output */
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    static const unsigned char *fill[16] = {
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,           /* unused */
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,           /* 1 - illegal; all opcodes are 2 bytes long */
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00",                     /* 4 */
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 3 - illegal */
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00",             /* 4 */
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 5 - illegal */
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00",     /* 6 */
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 7 - illegal */
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00"      /* 8 */
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00",
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 9 - illegal */
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00"      /* 10 */
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00",
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 11 - illegal */
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00"      /* 12 */
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00",
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL,                           /* 13 - illegal */
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (const unsigned char *)
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00"      /* 14 */
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "\x00\x00\x00\x00\x00\x00\x00\x00",
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        NULL                            /* 15 - illegal */
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    };
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return fill;
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned int
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_get_reg_size(/*@unused@*/ yasm_arch *arch, /*@unused@*/ uintptr_t reg)
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 16;
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic uintptr_t
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_reggroup_get_reg(/*@unused@*/ yasm_arch *arch,
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      /*@unused@*/ uintptr_t reggroup,
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      /*@unused@*/ unsigned long regindex)
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 0;
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_reg_print(/*@unused@*/ yasm_arch *arch, uintptr_t reg, FILE *f)
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "r%u", (unsigned int)(reg&7));
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      unsigned char *buf, size_t destsize, size_t valsize,
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      size_t shift, int warn)
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_error_set(YASM_ERROR_FLOATING_POINT,
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                   N_("LC-3b does not support floating point"));
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return 1;
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_effaddr *
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_ea_create_expr(yasm_arch *arch, yasm_expr *e)
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_effaddr *ea = yasm_xmalloc(sizeof(yasm_effaddr));
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_value_initialize(&ea->disp, e, 0);
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->need_nonzero_len = 0;
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->need_disp = 1;
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->nosplit = 0;
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->strong = 0;
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->segreg = 0;
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->pc_rel = 0;
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ea->not_pc_rel = 0;
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return ea;
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_lc3b__ea_destroy(/*@only@*/ yasm_effaddr *ea)
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_value_delete(&ea->disp);
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(ea);
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglc3b_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    fprintf(f, "%*sDisp:\n", indent_level, "");
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_value_print(&ea->disp, f, indent_level+1);
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define lc3b machines -- see arch.h for details */
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic yasm_arch_machine lc3b_machines[] = {
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { "LC-3b", "lc3b" },
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { NULL, NULL }
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Define arch structure -- see arch.h for details */
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_arch_module yasm_lc3b_LTX_arch = {
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "LC-3b",
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "lc3b",
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL,
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_create,
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_destroy,
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_get_machine,
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_get_address_size,
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_set_var,
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_lc3b__parse_check_insnprefix,
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_lc3b__parse_check_regtmod,
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_get_fill,
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_floatnum_tobytes,
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_lc3b__intnum_tobytes,
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_get_reg_size,
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_reggroup_get_reg,
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_reg_print,
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    NULL,       /*yasm_lc3b__segreg_print*/
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_ea_create_expr,
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_lc3b__ea_destroy,
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_ea_print,
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_lc3b__create_empty_insn,
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lc3b_machines,
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "lc3b",
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    16,
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    2
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
213