MipsMCInstLower.cpp revision b22c9289b0dd8255f63038e9bb8229111eb082ae
1c5707112e7635d1dd2f2cc9c4f42e79a51302ccaJia Liu//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===//
217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//
317a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//                     The LLVM Compiler Infrastructure
417a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//
517a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka// This file is distributed under the University of Illinois Open Source
617a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka// License. See LICENSE.TXT for details.
717a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//
817a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//===----------------------------------------------------------------------===//
917a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//
1017a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka// This file contains code to lower Mips MachineInstrs to their corresponding
1117a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka// MCInst records.
1217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//
1317a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka//===----------------------------------------------------------------------===//
1417a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
1579aa3417eb6f58d668aadfedf075240a41d35a26Craig Topper#include "MipsMCInstLower.h"
1617a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "MipsAsmPrinter.h"
1717a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "MipsInstrInfo.h"
1847b92f3d8362518596d57269dc53d985bc13323aBruno Cardoso Lopes#include "MCTargetDesc/MipsBaseInfo.h"
1917a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/CodeGen/MachineFunction.h"
2017a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/CodeGen/MachineInstr.h"
2117a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/CodeGen/MachineOperand.h"
2217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/MC/MCContext.h"
23ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes#include "llvm/MC/MCExpr.h"
2417a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/MC/MCInst.h"
2517a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka#include "llvm/Target/Mangler.h"
26421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
2717a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanakausing namespace llvm;
2817a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
29f93b86306683f8e860c8824efb717995cb072a70Akira HatanakaMipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
30f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  : AsmPrinter(asmprinter) {}
31f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka
32864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanakavoid MipsMCInstLower::Initialize(Mangler *M, MCContext *C) {
33f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  Mang = M;
34f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  Ctx = C;
35f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka}
3617a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
3717a2f8e551dd4a772d389d1a193235ae56f8a399Akira HatanakaMCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
3878d1b11aa57e5a2683e4be3baaaa9576ac04eea2Akira Hatanaka                                              MachineOperandType MOTy,
3978d1b11aa57e5a2683e4be3baaaa9576ac04eea2Akira Hatanaka                                              unsigned Offset) const {
40ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes  MCSymbolRefExpr::VariantKind Kind;
4117a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  const MCSymbol *Symbol;
4217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
4317a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  switch(MO.getTargetFlags()) {
44bc2198133a1836598b54b943420748e75d5dea94Craig Topper  default:                   llvm_unreachable("Invalid target flag!");
4582099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_NO_FLAG:   Kind = MCSymbolRefExpr::VK_None; break;
4682099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GPREL:     Kind = MCSymbolRefExpr::VK_Mips_GPREL; break;
4782099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT_CALL:  Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break;
4882099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT16:     Kind = MCSymbolRefExpr::VK_Mips_GOT16; break;
4982099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT:       Kind = MCSymbolRefExpr::VK_Mips_GOT; break;
5082099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_ABS_HI:    Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break;
5182099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_ABS_LO:    Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;
5282099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_TLSGD:     Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break;
5382099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_TLSLDM:    Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break;
5482099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break;
5582099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break;
5682099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOTTPREL:  Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break;
5782099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_TPREL_HI:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break;
5882099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_TPREL_LO:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break;
5982099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GPOFF_HI:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
6082099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GPOFF_LO:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
6182099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT_DISP:  Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break;
6282099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT_PAGE:  Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
6382099683060abb1f74453d06e78a3729a75ef7eeAkira Hatanaka  case MipsII::MO_GOT_OFST:  Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
64b22c9289b0dd8255f63038e9bb8229111eb082aeAkira Hatanaka  case MipsII::MO_HIGHER:    Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
65b22c9289b0dd8255f63038e9bb8229111eb082aeAkira Hatanaka  case MipsII::MO_HIGHEST:   Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
6617a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  }
6717a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
6817a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  switch (MOTy) {
69421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_MachineBasicBlock:
70421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = MO.getMBB()->getSymbol();
71421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
72421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
73421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_GlobalAddress:
74421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = Mang->getSymbol(MO.getGlobal());
75bed5b0db452f9f94facf260ca8667cf670c26c5cAkira Hatanaka    Offset += MO.getOffset();
76421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
77421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
78421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_BlockAddress:
79421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
80bed5b0db452f9f94facf260ca8667cf670c26c5cAkira Hatanaka    Offset += MO.getOffset();
81421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
82421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
83421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_ExternalSymbol:
84421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
85bed5b0db452f9f94facf260ca8667cf670c26c5cAkira Hatanaka    Offset += MO.getOffset();
86421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
87421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
88421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_JumpTableIndex:
89421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
90421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
91421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
92421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  case MachineOperand::MO_ConstantPoolIndex:
93421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
94bed5b0db452f9f94facf260ca8667cf670c26c5cAkira Hatanaka    Offset += MO.getOffset();
95421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    break;
96421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka
97421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka  default:
98421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    llvm_unreachable("<unknown operand type>");
9917a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  }
100bb481f882093fb738d2bb15610c79364bada5496Jia Liu
101f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx);
102ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes
103ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes  if (!Offset)
104ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes    return MCOperand::CreateExpr(MCSym);
105ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes
106ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes  // Assume offset is never negative.
107ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes  assert(Offset > 0);
108bb481f882093fb738d2bb15610c79364bada5496Jia Liu
109f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  const MCConstantExpr *OffsetExpr =  MCConstantExpr::Create(Offset, *Ctx);
110864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanaka  const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx);
111864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanaka  return MCOperand::CreateExpr(Add);
112ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes}
113ce1a538ab5b7ae7e0ed48d18c02571280fe105aaBruno Cardoso Lopes
11463b37f122d592c7451090ea32281686de967fcd4Akira Hatanaka/*
115864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanakastatic void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0,
116864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanaka                         const MCOperand &Opnd1,
117864f66085cd9543070ef01b9f7371c110ecd7898Akira Hatanaka                         const MCOperand &Opnd2 = MCOperand()) {
118f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  Inst.setOpcode(Opc);
119f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  Inst.addOperand(Opnd0);
120f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  Inst.addOperand(Opnd1);
121f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka  if (Opnd2.isValid())
122f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka    Inst.addOperand(Opnd2);
123f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka}
12463b37f122d592c7451090ea32281686de967fcd4Akira Hatanaka*/
125f93b86306683f8e860c8824efb717995cb072a70Akira Hatanaka
126864f66085cd9543070ef01b9f7371c110ecd7898Akira HatanakaMCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
127bb481f882093fb738d2bb15610c79364bada5496Jia Liu                                        unsigned offset) const {
1288957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  MachineOperandType MOTy = MO.getType();
129bb481f882093fb738d2bb15610c79364bada5496Jia Liu
1308957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  switch (MOTy) {
131bc2198133a1836598b54b943420748e75d5dea94Craig Topper  default: llvm_unreachable("unknown operand type");
1328957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_Register:
1338957481e6a3a4217499f739bae24401576ade078Akira Hatanaka    // Ignore all implicit register operands.
1348957481e6a3a4217499f739bae24401576ade078Akira Hatanaka    if (MO.isImplicit()) break;
1358957481e6a3a4217499f739bae24401576ade078Akira Hatanaka    return MCOperand::CreateReg(MO.getReg());
1368957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_Immediate:
137421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    return MCOperand::CreateImm(MO.getImm() + offset);
1388957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_MachineBasicBlock:
1398957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_GlobalAddress:
1408957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_ExternalSymbol:
1418957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_JumpTableIndex:
1428957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_ConstantPoolIndex:
1438957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  case MachineOperand::MO_BlockAddress:
144421455f1ea081e2e1767e782ac0d57ca55976e9bAkira Hatanaka    return LowerSymbolOperand(MO, MOTy, offset);
14571f0fc1ca88965b69b4b2c8794a7144bc93d4bbaJakob Stoklund Olesen  case MachineOperand::MO_RegisterMask:
14671f0fc1ca88965b69b4b2c8794a7144bc93d4bbaJakob Stoklund Olesen    break;
1478957481e6a3a4217499f739bae24401576ade078Akira Hatanaka }
1488957481e6a3a4217499f739bae24401576ade078Akira Hatanaka
1498957481e6a3a4217499f739bae24401576ade078Akira Hatanaka  return MCOperand();
1508957481e6a3a4217499f739bae24401576ade078Akira Hatanaka}
1518957481e6a3a4217499f739bae24401576ade078Akira Hatanaka
15217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanakavoid MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
15317a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  OutMI.setOpcode(MI->getOpcode());
154bb481f882093fb738d2bb15610c79364bada5496Jia Liu
15517a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
15617a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka    const MachineOperand &MO = MI->getOperand(i);
1578957481e6a3a4217499f739bae24401576ade078Akira Hatanaka    MCOperand MCOp = LowerOperand(MO);
15817a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka
1598957481e6a3a4217499f739bae24401576ade078Akira Hatanaka    if (MCOp.isValid())
1608957481e6a3a4217499f739bae24401576ade078Akira Hatanaka      OutMI.addOperand(MCOp);
16117a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka  }
16217a2f8e551dd4a772d389d1a193235ae56f8a399Akira Hatanaka}
163e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter
164e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter// If the D<shift> instruction has a shift amount that is greater
165e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
166e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Cartervoid MipsMCInstLower::LowerLargeShift(const MachineInstr *MI,
167e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter                                      MCInst& Inst,
168e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter                                      int64_t Shift) {
169e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  // rt
170e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  Inst.addOperand(LowerOperand(MI->getOperand(0)));
171e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  // rd
172e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  Inst.addOperand(LowerOperand(MI->getOperand(1)));
173e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  // saminus32
174e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  Inst.addOperand(MCOperand::CreateImm(Shift));
175e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter
176e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  switch (MI->getOpcode()) {
177e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  default:
178e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    // Calling function is not synchronized
179e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    llvm_unreachable("Unexpected shift instruction");
180e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    break;
181e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  case Mips::DSLL:
182e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    Inst.setOpcode(Mips::DSLL32);
183e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    break;
184e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  case Mips::DSRL:
185e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    Inst.setOpcode(Mips::DSRL32);
186e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    break;
187e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  case Mips::DSRA:
188e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    Inst.setOpcode(Mips::DSRA32);
189e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter    break;
190e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter  }
191e035f65b16956cdb7ba29e741b7e3c04a8ce4d24Jack Carter}
192